
/* cylinder drawing demo */
/* this demo demonstrates the various join styles

/* required include files */
#include <GL/gl.h>
#include "glut.h"
#include "GL/tube.h"

/* ------------------------------------------------------- */

/* the arrays in which we will store the polyline */
#define NPTS 100
double points [NPTS][3];
float colors [NPTS][3];
int idx = 0;

/* some utilities for filling that array */
#define PNT(x,y,z) { 			\
   points[idx][0] = x; 			\
   points[idx][1] = y; 			\
   points[idx][2] = z;			\
   idx ++;				\
}

#define COL(r,g,b) { 			\
   colors[idx][0] = r; 			\
   colors[idx][1] = g; 			\
   colors[idx][2] = b;			\
}

/* the arrays in which we will store the contour */
#define NCONTOUR 100
double contour_points [NCONTOUR][2];
int cidx = 0;

/* some utilities for filling that array */
#define C_PNT(x,y) { 			\
   contour_points[cidx][0] = x;		\
   contour_points[cidx][1] = y; 	\
   cidx ++;				\
}


/* ------------------------------------------------------- */
/* 
 * Initialize a bent shape with three segments. 
 * The data format is a polyline.
 *
 * NOTE that neither the first, nor the last segment are drawn.
 * The first & last segment serve only to determine that angle 
 * at which the endcaps are drawn.
 */

void InitCyl (void) {

   COL (0.0, 0.0, 0.0);
   PNT (16.0, 0.0, 0.0);

   COL (0.2, 0.8, 0.5);
   PNT (0.0, -16.0, 0.0);

   COL (0.0, 0.8, 0.3);
   PNT (-16.0, 0.0, 0.0);

   COL (0.8, 0.3, 0.0);
   PNT (0.0, 16.0, 0.0);

   COL (0.2, 0.3, 0.9);
   PNT (16.0, 0.0, 0.0);

   COL (0.2, 0.8, 0.5);
   PNT (0.0, -16.0, 0.0);

   COL (0.0, 0.0, 0.0);
   PNT (-16.0, 0.0, 0.0);

   C_PNT (-0.8, -0.5);
   C_PNT (-1.8, 0.0);
   C_PNT (-1.2, 0.3);
   C_PNT (-0.7, 0.8);
   C_PNT (-0.2, 1.3);
   C_PNT (0.0, 1.6);
   C_PNT (0.2, 1.3);
   C_PNT (0.7, 0.8);
   C_PNT (1.2, 0.3);
   C_PNT (1.8, 0.0);
   C_PNT (0.8, -0.5);

   gleSetJoinStyle (TUBE_JN_ANGLE | TUBE_CONTOUR_CLOSED | TUBE_JN_CAP);
}

float up_vector[3] = {0.0, -1.0, 0.0};

float lastx=0;
float lasty=0;
float newx=0;
float newy=0;

/* ------------------------------------------------------- */
/* draw the extrusion */

void DrawCyl (void) {
   double moved_contour [NCONTOUR][2];
   int style, save_style;
   int i;

   for (i=0; i<cidx; i++) {
      moved_contour[i][0] = contour_points [i][0];
      moved_contour[i][1] = contour_points [i][1] + 0.05 * (newy-200);
   }

   glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

   /* set up some matrices so that the object spins with the mouse */
   glPushMatrix ();
   glTranslatef (0.0, 8.0, -180.0);
   glRotatef (0.5*lastx, 0.0, 1.0, 0.0);

   gleExtrusion (cidx, moved_contour, contour_points, up_vector, 
                 idx, points, colors);

   glPopMatrix ();


   /* draw a seond copy, this time with the raw style, to compare
    * things against */
   glPushMatrix ();
   glTranslatef (0.0, -8.0, -180.0);
   glRotatef (0.5*lastx, 0.0, 1.0, 0.0);

   save_style = gleGetJoinStyle ();
   style = save_style;
   style &= ~TUBE_JN_MASK;
   style |= TUBE_JN_RAW;
   gleSetJoinStyle (style);

   gleExtrusion (cidx, moved_contour, contour_points, up_vector, 
                 idx, points, colors);

   gleSetJoinStyle (save_style);
   glPopMatrix ();

   glutSwapBuffers ();
}

/* ------------------------------------------------------- */
/* get notified of mouse motions */
void MouseMotion (int x, int y)
{
   lastx = newx;
   lasty = newy;
   newx = x;
   newy = y;
   glutPostRedisplay ();
}

/* ------------------------------------------------------- */
void JoinStyle (int msg) 
{
   int style;
   /* get the current joint style */
   style = gleGetJoinStyle ();

   /* there are four different join styles, 
    * and two different normal vector styles */
   switch (msg) {
      case 0:
         style &= ~TUBE_JN_MASK;
         style |= TUBE_JN_RAW;
         break;
      case 1:
         style &= ~TUBE_JN_MASK;
         style |= TUBE_JN_ANGLE;
         break;
      case 2:
         style &= ~TUBE_JN_MASK;
         style |= TUBE_JN_CUT;
         break;
      case 3:
         style &= ~TUBE_JN_MASK;
         style |= TUBE_JN_ROUND;
         break;

      case 20:
         style &= ~TUBE_NORM_MASK;
         style |= TUBE_NORM_FACET;
         break;
      case 21:
         style &= ~TUBE_NORM_MASK;
         style |= TUBE_NORM_EDGE;
         break;

      case 99:
         exit (0);

      default:
         break;
   }
   gleSetJoinStyle (style);
   glutPostRedisplay ();
}

/* ------------------------------------------------------- */
/* set up a light */
GLfloat lightOnePosition[] = {40.0, 40, 100.0, 0.0};
GLfloat lightOneColor[] = {0.99, 0.99, 0.99, 1.0}; 

GLfloat lightTwoPosition[] = {-40.0, 40, 100.0, 0.0};
GLfloat lightTwoColor[] = {0.99, 0.99, 0.99, 1.0}; 

/* ------------------------------------------------------- */
main (int argc, char * argv[]) {

   /* initialize glut */
   glutInit (&argc, argv);
   glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
   glutCreateWindow ("cylinder");
   glutDisplayFunc (DrawCyl);
   glutMotionFunc (MouseMotion);

   /* create popup menu */
   glutCreateMenu (JoinStyle);
   glutAddMenuEntry ("Raw Join Style", 0);
   glutAddMenuEntry ("Angle Join Style", 1);
   glutAddMenuEntry ("Cut Join Style", 2);
   glutAddMenuEntry ("Round Join Style", 3);
   glutAddMenuEntry ("------------------", 9999);
   glutAddMenuEntry ("Facet Normal Vectors", 20);
   glutAddMenuEntry ("Edge Normal Vectors", 21);
   glutAddMenuEntry ("------------------", 9999);
   glutAddMenuEntry ("Exit", 99);
   glutAttachMenu (GLUT_MIDDLE_BUTTON);

   /* initialize GL */
   glClearDepth (1.0);
   glEnable (GL_DEPTH_TEST);
   glClearColor (0.0, 0.0, 0.0, 0.0);
   glShadeModel (GL_SMOOTH);

   glMatrixMode (GL_PROJECTION);
   /* roughly, measured in centimeters */
   glFrustum (-9.0, 9.0, -9.0, 9.0, 50.0, 1150.0);
   glMatrixMode(GL_MODELVIEW);

   /* initialize lighting */
   glLightfv (GL_LIGHT0, GL_POSITION, lightOnePosition);
   glLightfv (GL_LIGHT0, GL_DIFFUSE, lightOneColor);
   glEnable (GL_LIGHT0);
   glLightfv (GL_LIGHT1, GL_POSITION, lightTwoPosition);
   glLightfv (GL_LIGHT1, GL_DIFFUSE, lightTwoColor);
   glEnable (GL_LIGHT1);
   glEnable (GL_LIGHTING);
   glColorMaterial (GL_FRONT_AND_BACK, GL_DIFFUSE);
   glEnable (GL_COLOR_MATERIAL);

   InitCyl ();

   glutMainLoop ();
}
/* ------------------ end of file ----------------------------- */
