INT32GP Graphics Programming: Tutorial #18
Polygonal Mesh - Box

B1.11 3:00 pm Tue 24 Sep 02
B1.11 12 midday Wed 25 Sep 02

Start with box0.c. This program renders a 3D hierarchical model of x, y, z-axes and has the following facilities. Render a polygonal mesh of a box with side length of one unit. The bottom left back vertex is at the origin (0,0,0) and the top right front vertex is at (1,1,1).
  1. Globally define relevant data structures. Refer to Lecture #19 for details of the specification.
  2. /*
    **  manage polygonal mesh
    */
    #define EDGES 12
    #define FACES 6
    typedef GLfloat vertexType[3];
    vertexType box[8]={
       {0.0,0.0,0.0},
       /* specify remaining 7 vertices */
    };
    GLint boxFace[FACES][4]={
       /* Identify each face using subscripts to the array of vertices.
       ** Each face has 4 vertices. Specify them in a right-handed
       ** (anti-clockwise) direction.
       */
    };
    enum {begin,end};
    GLint boxEdge[EDGES][2]={
       /* Identify each edge using subscripts to the array of vertices.
       ** Each edge has 2 vertices - the begin vertex  and the end vertex.
       */
    };
  3. Write a function to render a wireframe model of the box by joining the edges.
    void wireBox(){
       int i;
       glLineWidth(3);
       for (i=0;i<EDGES;i++){
          glBegin(GL_LINES);
             glVertex3fv(box[boxEdge[i][begin]]);
             glVertex3fv(box[boxEdge[i][end]]);
          glEnd();
       }
    }
  4. Render the wireframe model in magenta by adding (in the appropriate place) the following code to display().
    glColor3fv(colour[magenta]);
    wireBox();
  5. Write a function to render the outer faces of the box by traversing the vertices for each face in an anticlockwise direction.
    void outerBox(){
      int i,j;
      for(i=0;i<FACES;i++){
         glBegin(GL_POLYGON);
           for(j=0;j<4;j++)
             glVertex3fv(box[boxFace[i][j]]);
         glEnd();
     }
    }
  6. Render the outer faces in cyan. Add the following code to display(), before rendering the wireframe model.
  7. glColor3fv(colour[cyan]);
    outerBox();
  8. Write a function, innerBox() to render the inner faces of the box by traversing the vertices in a clockwise direction.
  9. Render the inner faces in cyan. Add the following code to display(), AFTER rendering the outer faces.
  10. glColor3fv(colour[red]);
    innerBox();
  11. Note that the box now appears to be red. There is no depth testing and the inner faces are rendered after the outer.
Toggle depth testing by pressing the d key.
  1. Find the following line in setUpGLUT.
    glutInitDisplayMode(GLUT_SINGLE|GLUT_RGB);
    Replace it with the following.
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
  2. Find the following line in display().
    glClear(GL_COLOR_BUFFER_BIT);
    Replace it with the following.
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  3. Edit the keyboard function to respond to the d key - suggestions below.
    static int depth=FALSE;
    
          case 'd': depth=!depth;
                    if(depth)
                       glEnable(GL_DEPTH_TEST);
                    else
                       glDisable(GL_DEPTH_TEST);
                    break;
  4. When you enable depth testing, the box colour should become cyan.
Move the box around in response to special function keys and rotate it around the y axis when the 'r' key is pressed. You attempted a similar exercise for the dancer hierarchical model.
  1. Set up appropriate global data structures, such as those below.
    /*
    ** manage model transforms
    */
    enum {boxMesh};
    GLdouble t[][3]={
       {0,0,0}
    };
    GLdouble ra[]={
       0,0
    };
    GLdouble r[][3]={
       {0,1,0}
    };
  2. Place the following code in the appropriate position in the display() function.
    glTranslated(t[boxMesh][x],t[boxMesh][y],t[boxMesh][z]);
    glRotated(ra[boxMesh],r[boxMesh][x],r[boxMesh][y],r[boxMesh][z]);
  3. Write a special key function. The one below is partially complete.
    void specialKeys(int key,int xMouse,int yMouse){
       int i;
       switch(key){
          case GLUT_KEY_PAGE_UP  : t[boxMesh][z]+= 0.1; break;
          case GLUT_KEY_PAGE_DOWN: t[boxMesh][z]+=-0.1; break;
       }
       glutPostRedisplay();
    }
  4. Register the callback in setUpGLUT.
    glutSpecialFunc(specialKeys);
  5. Edit the keyboard function to respond to the r key. Suggestion below.
    	      case 'r': ra[boxMesh]+=1.0;
                    if(ra[boxMesh]>=360)ra[boxMesh]=0;
                    break;
  6. Move the box around so that the camera passes inside the box.
  7. Is there a clear distinction between inner and outer faces? Or does OpenGL find it difficult to render them consistently?
We need back face culling.
  1. Add the following code to initialiseGL.
    glCullFace(GL_BACK);
    
  2. Toggle culling by pressing the c key.
        static int cull=FALSE;
    
          case 'c': cull=!cull;
                    if(cull)
                       glEnable(GL_CULL_FACE);
                    else
                       glDisable(GL_CULL_FACE);
                    break;
What happens if we cull GL_FRONT_AND_BACK or GL_FRONT?

Fran Soddell email:F.Soddell@bendigo.latrobe.edu.au
last updated 23 September 2002