[ Previous | Next | Contents | Glossary | Home | Search ]
GL3.2 for AIX: Graphics Library (GL) Technical Reference

cylinder2.c Example C Language Program

/*
 *  cylinder2.c:
 *
 *  This program displays two intersecting cylinders, using a
 *  different surface material for each cylinder.  In addition, each
 *  cylinder is lit by two light source.
 *
 *  This program requires the z-buffer option.
 *
 */
#include <gl.h>
#include <math.h>
#include <stdio.h>
#define RADIUS 0.9
#define TWOPI 6.28318530
#define PI 3.14159265
/* define black RGB color */
float  blackvec[3] = {0.0, 0.0, 0.0};   
Matrix idmat = {1.0,0.0,0.0,0.0,  /* identity matrix */
                0.0,1.0,0.0,0.0,
      0.0,0.0,1.0,0.0,
      0.0,0.0,0.0,1.0};
/* define a polygon with some structures */
typedef struct {   /* 3-D vertex structure */
    Coord x;
    Coord y;
    Coord z;
} POINT;
typedef struct {   /* lighted polygon struct */
    POINT vertex[4];
    POINT normal[4];
} POLYGON;
int number_of_polys;   /* cylinder polygon count */
POLYGON *polygon;   /* polygon list pointer */
/* define property arrays */
float shiny_material[] =  
    {SPECULAR,  0.8, 0.8, 0.8, /* light gray reflectance */
     DIFFUSE,   0.4, 0.4, 0.4, /* gray reflectance */
     SHININESS, 30.0,          /* focused highlight */
     LMNULL};
float purple_material[] = 
    {SPECULAR,  0.3, 0.3, 0.3, /* gray reflectance */
     DIFFUSE,   0.8, 0.0, 0.8, /* purple reflectance */
     SHININESS, 3.0,           /* unfocused highlight */
     AMBIENT,   0.2,0.0,0.2,   /* purple reflectance */
     LMNULL};
float blue_light[] =
    {LCOLOR,    0.0,0.0,0.6,   /* blue light */
     POSITION,  0.0,0.1,0.0,0.0,  /* Y axis at infinity */
     LMNULL};
/*
** def_light_calc()
** Tell the Graphics Library to DEFINE a
** lighting calculation that accounts for
** ambient, diffuse, and specular reflection.
** This lighting calculation defines a second
** material and light source.
*/ 
def_light_calc() { 
    lmdef(DEFMATERIAL, 1, 11, shiny_material); 
    lmdef(DEFMATERIAL, 2, 15, purple_material);
    lmdef(DEFLIGHT, 1, 0, NULL);
    lmdef(DEFLIGHT, 2, 10, blue_light);
    lmdef(DEFLMODEL, 1, 0, NULL);
}
/*
** use_light_calc()
** Tell the Graphics Library to USE
** the lighting calculation that we 
** defined earlier.
*/
use_light_calc()
{
    lmbind(LIGHT0, 1);   /* use light source description 1 */
    lmbind(LIGHT1, 2);   /* use light source description 2 */
    lmbind(LMODEL, 1);   /* use lighting model 1 */
}
/* 
** make_cylinder()
** Draw a cylinder using (2 * n) polygons
** to approximate the curvature and n polygons
** to describe the length. This requires (2 * n^2)
** polygons to describe the cylinder. Compute
** the surface normal at each vertex so we can
** use the hardware lighting facility to perform
** lighting calculations.
*/
make_cylinder(n)
int n;
{
    POLYGON *p;      /* polygon list pointer */
    float theta, dtheta,/* current angle and angle */
              /* increment around section */
     x, dx;   /* current position and */
         /* increment along cylinder side */
    int vertex_i;   /* vertex counter */
    /* allocate and point to enough */
    /* memory for all the polygons */
    number_of_polys = 2 * n * n;
    p = polygon = (POLYGON *)
   malloc(number_of_polys * sizeof(POLYGON));
    dx = 3.0/n;   /* n polygons for 3.0 units of length */
    dtheta = PI/n; /* length of polygon along curvature */
    /* for each layer of polygons */
    /* along length of cylinder ... */
    for (x = -1.5; x < 1.5; x = x+dx) {
   /* ... and for each polygon */
   /* describing the circumference */
        for (theta = 0.0; theta < TWOPI; theta += dtheta) {   
       /* calculate the four points */
       /* describing the polygon */
       p->vertex[0].x = p->vertex[1].x = x;
       p->vertex[0].y = p->vertex[3].y = 
      RADIUS * cos(theta);
       p->vertex[0].z = p->vertex[3].z = 
      RADIUS * sin(theta);
       p->vertex[1].y = p->vertex[2].y = 
      RADIUS * cos(theta + dtheta);
       p->vertex[1].z = p->vertex[2].z = 
      RADIUS * sin(theta + dtheta);
       p->vertex[2].x = p->vertex[3].x = x + dx;
       /* calculate the four normals of unit length */
       for (vertex_i = 0; vertex_i < 4; vertex_i++) {
      p->normal[vertex_i].x = 0;
      p->normal[vertex_i].y = 
          p->vertex[vertex_i].y / RADIUS;
      p->normal[vertex_i].z = 
          p->vertex[vertex_i].z / RADIUS;
       }
       p++; 
   }
    }
}
/* 
** draw_cylinder()
** This subroutine increments through the 4
** vertices describing each polygon of the
** cylinder defined in make_cylinder.  Note
** how a normal is sent to the graphics
** hardware before each vertex so that the
** lighting facility will compute the color
** for each vertex based on the lighting
** parameters that we are using.
*/
draw_cylinder()
{
    POLYGON *p;    /* pointer into polygon list */
    int poly_i;    /* polygon counter */
    /* start at first polygon and */
    /* increment through all of them */
    p = polygon;
    for (poly_i = 0; poly_i < number_of_polys; poly_i++) {
   bgnpolygon();   /* describe the polygon */
            n3f(&p->normal[0]);  
            v3f(&p->vertex[0]);  
            n3f(&p->normal[1]);  
            v3f(&p->vertex[1]);  
            n3f(&p->normal[2]);  
            v3f(&p->vertex[2]);  
            n3f(&p->normal[3]);  
            v3f(&p->vertex[3]);  
   endpolygon();
   p++;      /* go to the next polygon */
    }
}
/*
** Main Program 
*/
main()
{
    int i;
    /* set up graphics environment */
    prefposition(100, 600, 100, 600);
    winopen("cylinder");
    RGBmode();
    doublebuffer();
    gconfig();
    lsetdepth(0, 0x7FFFFF);
    zbuffer(TRUE);
    /* Use mmode() to set up projection */
    /* and viewing matrices for lighting */
    mmode(MVIEWING);      
    perspective(400, 1.0, 4.0, 12.0);
    loadmatrix(idmat);
    lookat(0.0,0.0,8.0,0.0,0.0,0.0,0);
    /* let there be light !!!! */
    def_light_calc();
    use_light_calc();
    /* Rotate cylinders in 2 deg. increments */
    /* about Y and Z axis for 180 frames */
    make_cylinder(25);
    for (i = 0; i < 180; i++) {   
        c3f(blackvec);        
        clear();
   zclear();
   pushmatrix();
           rot(i * 2.0, 'Z');
       rot(i * 2.0, 'Y'); 
       /* use white shiny material for cyl 1*/
       lmbind(MATERIAL, 1);
            draw_cylinder();
       pushmatrix();        
           rot(90.0, 'Y');
           scale(0.9,0.9,0.9);
      /* use purple rough material for cyl 2 */
           lmbind(MATERIAL, 2);
                draw_cylinder();
       popmatrix();
   popmatrix();
   swapbuffers();
    }
    sleep(3);
}

Related Information

The bgnpolygon or endpolygon subroutine, lmbind subroutine, lmdef subroutine, n3f subroutine, scale subroutine, v subroutine.

Lighting Basics in GL3.2 Version 4 for AIX: Programming Concepts.


[ Previous | Next | Contents | Glossary | Home | Search ]