/*****************************2002*************************************/
/****       skel.c = OpenSkelGlut.c = Noosh97 with CAVE removed    ****/
/****      (C) 1994--2002 Board of Trustees University of Illinois ****/ 
/****      A Model Real-Time Interactive  C/OpenGL/GLUT  Animator  ****/
/****    George Francis, Stuart Levy, Glenn Chappell, Chris Hartman****/
/****    e-mail  gfrancis@math.uiuc.edu : revised 2jan02 by gkf    ****/
/**********************************************************************/

/* A C++ version for CS293 at University of Alaska Fairbanks
   updated from above by Chris Hartman, 2/2003               */
#include <cstdlib>
#include <cstdio>
#include <GL/glut.h>
#include <sys/timeb.h>     /* sgi  <sys/time.h> */
#define _USE_MATH_DEFINES  // So Windows will define M_PI
#include <cmath>
#include <algorithm>
#include <iostream>
#include <time.h>
using namespace std;

#define  CLAMP(x,u,v)     (x<u? u : (x>v ? v: x))
#define  ABS(u)           ((u)<0 ? -(u): (u))
#define  FOR(a,b,c)       for((a)=(b);(a)<(c);(a)++)
#define  DOT(p,q)         ((p)[0]*(q)[0]+(p)[1]*(q)[1]+(p)[2]*(q)[2])
#define  NRM(p)           sqrt(DOT((p),(p)))
#define  DG            M_PI/180
#define  S(u)          sin(u*DG)
#define  C(u)          cos(u*DG)
#define  CLAMP(x,u,v) (x<u? u : (x>v ? v: x))
#define  random        rand        /* library dependent name  */
#define IFCLICK(K,a){static int ff=1; if(getbutton(K))ff=1-ff; if(ff){a} }
#define MERIDIANS 32
#define LATITUDES 32
#define MANYSTARS 10000

#define max(u,v) (u<v ? v : u)  //compatibility on my system (T. Veazey 2/2003)
#define M_PI 355./113.

/************************** global variables **************************/
int win=2;                 /* used once to choose window size         */
double mysiz,speed, torq, focal, wfar; /* navigation control variables */
unsigned int PAW,XX,YY,SHIF;  /* used in chaptrack gluttery           */
int xwide,yhigh;                /* viewportery width and height       */
int mode,msg,binoc;       /* viewing globals */
#define FLYMODE  (0)         /* yellow: turns around head as center   */
#define TURNMODE (1)         /* purple: turns around object center    */
int ii, jj, kk;  double tmp, temp;          /* saves gray hairs later  */
double aff[16], starmat[16], mat[16];   /* OpenGL placement matrices   */
double nose;                       /* to eye distance in console       */
char clefs[128];                  /* which keys were pressed last     */
int landGenFirst=1;
/*********************** steering *************************************/
/**********************************************************************/
void deFault(void){         /* (Z)ap also restores these assignments  */ 
  msg=1; binoc=0; nose=.06; mode=TURNMODE;       /* gadget parameters */   
  speed=.02; torq=.02; focal = 2.; wfar=13; mysiz=.01;
  FOR(ii,0,16) starmat[ii]=aff[ii] = (ii/4==ii%4); /* identity matrix */ 
  aff[12]=0; aff[13]= 0; aff[14]= -4.2; /* place where we can see it  */
}
/*************************** scenery **********************************/


#define MAXLEVEL 5		//maximum recursive level of the fractal
	//Note: MAXLEVEL MUST BE >= 1
#define INITHEIGHT 1.	//initial height of mountain
#define LANDW 5.		//maximum deviation from the y-axis
#define LANDL 5.		//maximum deviation from the x-axis

//structure to define a point
typedef struct
{
	float x;
	float y;
	float z;
}point;



point *landpt;		//array of points
int ptptr;			//"pointer" to the current point in the array

//bubblesort modified to break the points down into their 8 groups
void sortIt(int size)
{
	bool flipped = true;
	point temp;
	
	for(int k=0; k<size; k+=size/8)
	{
		for(int i=k; i<k+size/8; i++)
		{
			flipped=false;
			for(int j=k+size/8-1; j>=k+1; j--)
			{
				if( fabs(landpt[j].x) < fabs(landpt[j-1].x))
				{
					temp.x = landpt[j].x;
					temp.y = landpt[j].y;
					temp.z = landpt[j].z;
					landpt[j].x = landpt[j-1].x;
					landpt[j].y = landpt[j-1].y;
					landpt[j].z = landpt[j-1].z;
					landpt[j-1].x = temp.x;
					landpt[j-1].y = temp.y;
					landpt[j-1].z = temp.z;
					flipped=true;
				}
				else if( landpt[j].x == 0 )
				{
					if( fabs(landpt[j].y) < fabs(landpt[j-1].y))
					{
						temp.x = landpt[j].x;
						temp.y = landpt[j].y;
						temp.z = landpt[j].z;
						landpt[j].x = landpt[j-1].x;
						landpt[j].y = landpt[j-1].y;
						landpt[j].z = landpt[j-1].z;
						landpt[j-1].x = temp.x;
						landpt[j-1].y = temp.y;
						landpt[j-1].z = temp.z;
						flipped=true;
					}
				}
			}
		}
		flipped = true;
	}
}

void mountain(int level, GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
{
	//generate a new point based on the two points passed in
	GLfloat nx, ny, nz;
	nx = (x1+x2)/2.;
	ny = (y1+y2)/2.;
	nz = (z1+z2)/2.;

	//generate a new height for this point
	nz+= (rand()%3 ? -1. : 1.) * nz/5.;

	if(level)
	{
		//pass this point along recursively...
		mountain(level-1,x1,y1,z1,nx,ny,nz);
		mountain(level-1,nx,ny,nz,x1,y1,z1);
	}
	else
	{
		//...or add this point to the array
		landpt[ptptr/2].x = nx;
		landpt[ptptr/2].y = ny;
		landpt[ptptr/2].z = nz;

		if(landpt[ptptr/2-1].x == x1 && landpt[ptptr/2-1].y == y1)
			landpt[ptptr/2-1].z = z1;

		ptptr++;
	}
}

void landgen(void)
{
	int level = 4, i;
	static int arraySize = pow(2.0,MAXLEVEL+1);
	if(landGenFirst)
	{
		ptptr = 0;
		landGenFirst = 0;
		landpt = new point[arraySize];
		srand(time(NULL));
		ptptr = 0;

		//calls to the recursive function mountain to generate the points plotted
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,LANDW,LANDL,0.0);
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,  0.0,LANDL,0.0);
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,-1. * LANDW,LANDL,0.0);
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,-1. * LANDW,0.0,0.0);
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,-1. * LANDW,-1. * LANDL,0.0);
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,  0.0,-1. * LANDL,0.0);
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,LANDW,-1. * LANDL,0.0);
		mountain(MAXLEVEL-1,0.0,0.0,INITHEIGHT,LANDW,0.0,0.0);

		//a bubblesort to order the points from smallest to largest w/in their respected sets
		sortIt(arraySize);
	}

	for(i=0; i<arraySize/8*7; i++)
	{
		if((i+1)%(arraySize/8) == 0) continue;
		
		glBegin(GL_TRIANGLE_STRIP);

		glVertex3f(landpt[i].x,landpt[i].y,landpt[i].z);
		glVertex3f(landpt[i+arraySize/8].x,landpt[i+arraySize/8].y,landpt[i+arraySize/8].z);
		glVertex3f(landpt[i+1].x,landpt[i+1].y,landpt[i+1].z);
		glVertex3f(landpt[i+arraySize/8+1].x,landpt[i+arraySize/8+1].y,landpt[i+arraySize/8+1].z);

		glEnd();
	}

	for(i=arraySize/8*7; i<arraySize-1; i++)
	{
		glBegin(GL_TRIANGLE_STRIP);

		glVertex3f(landpt[i].x,landpt[i].y,landpt[i].z);
		glVertex3f(landpt[i-arraySize/8*7].x,landpt[i-arraySize/8*7].y,landpt[i-arraySize/8*7].z);
		glVertex3f(landpt[i+1].x,landpt[i+1].y,landpt[i+1].z);
		glVertex3f(landpt[i-arraySize/8*7+1].x,landpt[i-arraySize/8*7+1].y,landpt[i-arraySize/8*7+1].z);

		glEnd();
	}

	glBegin(GL_TRIANGLE_FAN);

	glVertex3f(0.0,0.0,INITHEIGHT);
	glVertex3f(landpt[0].x,landpt[0].y,landpt[0].z);
	glVertex3f(landpt[arraySize/8].x,landpt[arraySize/8].y,landpt[arraySize/8].z);
	glVertex3f(landpt[arraySize/4].x,landpt[arraySize/4].y,landpt[arraySize/4].z);
	glVertex3f(landpt[arraySize/8*3].x,landpt[arraySize/8*3].y,landpt[arraySize/8*3].z);
	glVertex3f(landpt[arraySize/2].x,landpt[arraySize/2].y,landpt[arraySize/2].z);
	glVertex3f(landpt[arraySize/8*5].x,landpt[arraySize/8*5].y,landpt[arraySize/8*5].z);
	glVertex3f(landpt[arraySize/4*3].x,landpt[arraySize/4*3].y,landpt[arraySize/4*3].z);
	glVertex3f(landpt[arraySize/8*7].x,landpt[arraySize/8*7].y,landpt[arraySize/8*7].z);
	glVertex3f(landpt[0].x,landpt[0].y,landpt[0].z);

	glEnd();
}


/**********************************************************************/
void drawall(void)
{
	//set up the lighting
	glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
	GLfloat LightSpecular[] = { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat LightAmbient[]= { 0.8f, 0.8f, 0.8f, 1.0f };
	GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f, 1.0f };
	GLfloat LightPosition[]= { 0.0f, 0.0f, 2.0f, 1.0f };
	GLfloat LightDirection[] = {0.0f, 0.0f, -1.0f};

	glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmbient);
	glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
	glLightfv(GL_LIGHT0, GL_SPECULAR, LightSpecular);
	glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
	glLightf(GL_LIGHT0, GL_CONSTANT_ATTENUATION, .75);
	glLightf(GL_LIGHT0, GL_LINEAR_ATTENUATION, .5);
	glLightf(GL_LIGHT0, GL_QUADRATIC_ATTENUATION, 0.5);
	glEnable(GL_LIGHT0);
	glEnable(GL_LIGHTING);

	//give our land some material lighting properties
	GLfloat land_light[] = {0.0,1.0,0.0};
	GLfloat amb_land_light[] = {0.0,0.4,0.0};
	GLfloat spec_land_light[] = {1.0,1.0,1.0};
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec_land_light);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, land_light);
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb_land_light);
	glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 100.);

	//generate our terrain
	landgen();
}
/**********************************************************************/
void drawstars(void){  /* replace with SLevy's much prettier stars    */ 
	glDisable(GL_LIGHTING);
  static double star[MANYSTARS][3];
  static int virgin=1;
  if(virgin)
  {             /* first time through set up the stars      */
     FOR(ii,0,MANYSTARS)
	 { /* in a unit cube then  on unit sphere      */
       FOR(jj,0,3)star[ii][jj]  = (double)random()/RAND_MAX - 0.5;
       tmp=NRM(star[ii]); 
	   FOR(jj,0,3)star[ii][jj]/=tmp;        
     }
   virgin=0; /* never again */
  }
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix();           /* optional insurance or superstition    */ 
    glMultMatrixd(starmat);
    glColor3f(0.8,0.9,1.0);        
    glBegin(GL_POINTS);
      FOR(ii,0,MANYSTARS)glVertex3dv(star[ii]); 
    glEnd();
   //glutWireTeapot(1);  //if you prefer one on the firmament instead  */
  glPopMatrix();            /* optional insurance or superstition    */
  glClear(GL_DEPTH_BUFFER_BIT); /* put the stars at infinity         */
  glEnable(GL_LIGHTING);
}
/************************ steering ***********************************/
void arguments(int argc,char **argv){           /* Pat Hanrahan 1989 */
      while(--argc){++argv; if(argv[0][0]=='-')switch(argv[0][1]){
      case 'w': win =atoi(argv[1]); argv++; argc--; break;
   }}}
/**********************************************************************/
int number, hasnumber, decimal, sign;  /* globals for SLevy's gadgets */
   /* these are assigned in keyboard() but used by these factor fcns  */
double getnumber(double dflt){    /*  from keyboard, factor of bump()   */
     double v = (sign ? -number : number);  /* positive or negative nr */
     if(!hasnumber) return dflt;       /* if no new nr use old on     */
     return decimal>0 ? v/(double)decimal : v;
}
void bump(double *val, double incr){          /* SLevy 98 */
  double by = fabs(incr);   /* wizard speak ... best not mess with it  */ 
  char fmt[8], code[32];
  int digits = 1;
  if(hasnumber) {
    *val = getnumber(0);
    return;
  }
  if(by <= .003) digits = 3;
  else if(by <= .03) digits = 2;
  sprintf(fmt, "%%.%de", digits);
  sprintf(code, fmt, *val * (1 + incr));
  sscanf(code, "%f", val);
}
/********************from SLevy 2jan02 ********************************/
int getbutton(char key) { 
    int uu = clefs[key & 127]; clefs[key & 127]=0; return uu;
}
/**********************************************************************/
void keyboard(unsigned char key, int x, int y){
   clefs[key&127]=1;  /* globalize the keys that were pressed         */ 
#define  IF(K)            if(key==K)  
#define  PRESS(K,A,b)     IF(K){b;} IF(K-32){A;}  /* catch upper case */
#define  TOGGLE(K,flg)    IF(K){(flg) = 1-(flg); }
#define  CYCLE(K,f,m)   PRESS((K),(f)=(((f)+(m)-1)%(m)),(f)=(++(f)%(m)))
#define  SLIDI(K,f,m,M)   PRESS(K,(--f<m?m:f), (++f>M?M:f)) 
#define  SLIDF(K,f,m,M,d) PRESS(K,((f -= d)<m?m:f), ((f += d)>M?M:f))
/* Only 127 ASCII chars are processed in this GLUT callback function  */ 
/* Use the specialkeybo function for the special keys                 */ 
   IF(27) { exit(0); }                           /* ESC exit          */
   TOGGLE('v',binoc);                            /* cross-eyed STEREO */
   TOGGLE(' ',mode);                             /* space key         */
   CYCLE('w',msg,3);           /* writing on/off/speedometer+bullseye */
   PRESS('n', nose -= .001 , nose += .001 );     /* for binoculars    */
   PRESS('s', bump(&speed,.02), bump(&speed,-.02));/* flying speed    */ 
   PRESS('q', bump(&torq, .02), bump(&torq, -.02)); /* turning speed  */
   PRESS('o', focal *= 1.1 , focal /= 1.1)       /* telephoto         */
   PRESS('i', mysiz /= 1.1, mysiz *= 1.1)        /* rescale the world */
   PRESS('p', wfar *= 1.01 , wfar   /= 1.01)   /* rear clipping plane */
   PRESS('z', deFault(), deFault());             /* zap changes       */
   TOGGLE('`',landGenFirst);
/********** SLevy's parser creates the input decimal ******************/
   if(key >= '0' && key <= '9'){         /* if key is a digit numeral */
          hasnumber = 1; number = number*10+key-'0'; decimal *= 10; } 
   else if(key == '.') { decimal = 1; }  /* it's a decimal !          */
   else if(key == '-') { sign = -1; }    /* it's negative  !          */
   else { hasnumber = number = decimal = sign = 0;} /* erase mess     */
   glutPostRedisplay();                 /* in case window was resized */
}
/**********************************************************************/
void specialkeybo(int key, int x, int y){
  clefs[0]= key ;
  switch(key){    /*  HOME END PAGE_DOWN RIGHT F1 etc  see glut.h    */
  /* default: fprintf(stderr,"non-ASCII char [%d] pressed.\n", key); */
  }
  hasnumber=number=decimal=0; glutPostRedisplay();
}
/**********************************************************************/
double speedometer(void){                      /* this one is for win32*/ 
  double dbl; static double rate; static int ii=0;
  static struct timeb lnow, lthen;
    if(++ii % 8 == 0){                 /* 8 times around measure time */
	   ftime(&lnow);
		dbl =  (double)(lnow.time - lthen.time)
			 +(double)(lnow.millitm - lthen.millitm)/1000;
		lthen = lnow;  rate = 8/dbl;
      }
    return((double)rate);
}
/**********************************************************************/
void char2wall(double x,double y,double z, char buf[]){
     char *p; glRasterPos3f(x,y,z);
     for(p = buf;*p;p++) glutBitmapCharacter(GLUT_BITMAP_9_BY_15,*p);
}
/**********************************************************************/
void messages(void){
	glDisable(GL_LIGHTING);
	char buf[256]; 
  /* console messages are done differently from cave */
#define  LABEL(x,y,W,u) {sprintf(buf,(W),(u));char2wall(x,y,0.,buf);}
  glMatrixMode(GL_PROJECTION); glPushMatrix();  /* new projection matrix */
  glLoadIdentity(); gluOrtho2D(0,3000,0,3000);  /* new 2D coordinates */
  glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();
      if(mode==TURNMODE) glColor3f(1.,0.,1.); else glColor3f(1.,1.,0.);
      LABEL(1500,1500,"%s","o"); /* place a bullseye dead center */
      LABEL(80,150,"%4.1f fps",speedometer());
      if(msg==2)return;  //try this
      LABEL(80,2840,\
      "(ESC)ape (MAUS2)Fore (BAR)%s (H)omotopy (W)riting",
             mode?"TURNMODE":"FLYMODE");
      LABEL(10,80,"illiSkel-2002 engine by Francis, Levy, Bourd, Hartman,\
& Chappell, U Illinois, 1995..2002 %s","");
      LABEL(10,10,"Recursive Generation of a 3-Dimensional Fractal Mountain by Veazey, 2003 %s","");
      LABEL(80,2770,"(N)ose   %0.3f",nose);
      LABEL(80,2700,"[S]peed  %0.4f",speed);
      LABEL(80,2630," tor[Q] %0.4f",torq);
      LABEL(80,2560,"near clipper %g", mysiz*focal);
      LABEL(80,2490,"f(O)cal factor %g",focal);
      LABEL(80,2420,"my s(I)ze %.2g",mysiz);
      LABEL(80,2350,"far cli(P)per= %.2g",wfar); 
      LABEL(80,2280,"(Z)ap %s","");
    glPopMatrix();
    glMatrixMode(GL_PROJECTION); glPopMatrix();
	glEnable(GL_LIGHTING);
} 
/************************ navigation **********************************/
void chaptrack(int paw,int xx,int yy,int shif){/* Glenn Chappell 1992 */
   long dx,dy; 
   dx = xx -.5*xwide; dx = abs(dx)>5?dx:0;        /* 5 pixel latency  */
   dy = yy -.5*yhigh; dy = abs(dy)>5?dy:0; 
   glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity();
   if(mode==TURNMODE) glTranslatef(aff[12],aff[13],aff[14]);
   glRotatef(dx*torq,0.,1.,0.); glRotatef(dy*torq,1.,0.,0.);
   if(paw&(1<<GLUT_RIGHT_BUTTON ))glRotatef(shif?-10:-1,0.,0.,1.);
   if(paw&(1<<GLUT_LEFT_BUTTON  ))glRotatef(shif?10:1,0.,0.,1.);
   if(mode==FLYMODE){
      glPushMatrix();
      glMultMatrixd(starmat);
      glGetDoublev(GL_MODELVIEW_MATRIX,starmat);
      glPopMatrix(); }
   if(paw&(1<<GLUT_MIDDLE_BUTTON))glTranslatef(0.,0.,shif?-speed:speed);
   if(clefs[0]==GLUT_KEY_UP) glTranslatef(0.,0., speed);
   if(clefs[0]==GLUT_KEY_DOWN) glTranslatef(0.,0., -speed);
   if(clefs[0]==GLUT_KEY_LEFT) glTranslatef(-speed,0.,0.);
   if(clefs[0]==GLUT_KEY_RIGHT) glTranslatef(speed,0.,0.);
   if(clefs[0]==GLUT_KEY_PAGE_UP) glTranslatef(0., speed,0.);
   if(clefs[0]==GLUT_KEY_PAGE_DOWN) glTranslatef(0.,-speed,0.);
   if(mode==TURNMODE) glTranslatef(-aff[12],-aff[13],-aff[14]);
   glMultMatrixd(aff); 
   glGetDoublev(GL_MODELVIEW_MATRIX,aff);
   glPopMatrix();
}
/************************* scenery ************************************/
void reshaped(int xx, int yy){xwide=xx ; yhigh=yy;} /*win width,height*/
/**********************************************************************/
void drawcons(void){ double asp =(double)xwide/yhigh; /* aspect ratio   */
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
  glClearColor(0,0,0,0);   /* base color, try (.1,.2,.3,0.)           */  
  if(binoc) glViewport(0,yhigh/4,xwide/2,yhigh/2);
  glMatrixMode(GL_PROJECTION); glLoadIdentity();
  glFrustum(-mysiz*asp,mysiz*asp,-mysiz,mysiz,mysiz*focal,wfar); 
  glMatrixMode(GL_MODELVIEW); glLoadIdentity();
  drawstars();
  glTranslatef(-binoc*nose,0.0,0.0);
  glMultMatrixd(aff);
  drawall();
  if(binoc){
      glViewport(xwide/2,yhigh/4,xwide/2,yhigh/2); 
      glMatrixMode(GL_MODELVIEW);
      glLoadIdentity();
      drawstars();
      glTranslatef(binoc*nose,0.0,0.0);
      glMultMatrixd(aff);
      drawall();
    }
  glViewport(0,0,xwide,yhigh);
  if(msg) ::messages();
  glutSwapBuffers();
}
/************************** steering **********************************/
void idle(void){            /* do this when nothing else is happening */
   glutPostRedisplay();                          /* redraw the window */
   IFCLICK('=',chaptrack(PAW,XX,YY,SHIF);)       /* bypass navigation */
   glDisable(GL_DEPTH_TEST);                   /* bypass depth buffer */ 
   IFCLICK('-',glEnable(GL_DEPTH_TEST); )      /* bypass depth buffer */
}
/**********************************************************************/
void mousepushed(int but,int stat,int x,int y){
  if(stat==GLUT_DOWN) PAW |= (1<<but); /*key came down and called back*/
  else PAW &= (-1 ^ (1<<but));              /* on the wayup erase flag*/ 
  XX=x; YY=y;        /* position in window coordinates (pos integers) */ 
  SHIF=(glutGetModifiers()==GLUT_ACTIVE_SHIFT)?1:0;  /* shift down too*/
}
/**********************************************************************/
void mousemoved(int x,int y){ XX=x; YY=y; }
/***************** one ring to rule the all ***************************/
int main(int argc, char **argv){  
   arguments(argc,argv);                      /* from the commandline */
   deFault();                         /* values of control parameters */
       glutInit(&argc, argv);  
       glutInitDisplayMode(GLUT_DOUBLE|GLUT_DEPTH);
       switch(win){ 
           case 0: break;                   /* manage your own window */
           case 1: glutInitWindowSize(640, 480);
                   glutInitWindowPosition(100,100); break;
           case 2: glutInitWindowPosition(0,0); break;
         }
       glutCreateWindow("<* illiSkel 2002 in C/OpenGL/GLUT *>");
       if(win==2) glutFullScreen();
       glEnable(GL_DEPTH_TEST);                    /* enable z-buffer */
       glutDisplayFunc(drawcons); 
               /* the following are optional for interactive control  */ 
       glutKeyboardFunc(keyboard);
       glutSpecialFunc(specialkeybo);
       glutMouseFunc(mousepushed);
       glutMotionFunc(mousemoved);       
       glutPassiveMotionFunc(mousemoved); 
                                      /*  beyond here all are needed  */
       glutReshapeFunc(reshaped);
       glutIdleFunc(idle);             
       glutMainLoop();

	   return 0;
}
/**********************************************************************/
 
