
/* ==========================================================================
                               MAIN_C
=============================================================================
    DESCRIPTION
	This is the main file of facade. It contains the initializes the face, gl,
	glut and the face parameters. It also contains the main loop which polls
	the keyboard and mouse via glut. The important routines are faceinit,
	display and main.

    HISTORY
	2/8/03 andrew park     fixed reset and added glMultMatrixf for rotation
	2/6/03 alain deschenes moved glut header to win system
    3/07   gary king       added windows timing functions so animation runs at 30fps
    1/01   steve dipaola   ported  from sgi via glut example files

    FUNCTION NAMES

    movelight 		-- moves the light source.
    rotatexface 	-- rotates the face about the X axis.
    rotateyface 	-- rotates the face about the Y axis.
    myinit 		-- local initialization.
    faceinit 		-- glutInit(&argc, argv); initialize the face data.
    display 		-- display functions.
    myReshape 		-- window respahe callback.
    error_exit		-- error function.
    usage		-- usage function.
    GLenum Key 		-- keyboard mappings.
    main 		-- main program.

    print_help - as stated
	void InitParams() - initialized face parameters to their default values

    C SPECIFICATIONS

    void movelight 	( int x, int y )
    void rotatexface 	( int x, int y )
    void rotateyface 	( int x, int y )
    void myinit 	( void )
    faceinit 		( void )
    void display 	( void )
    void myReshape 	( GLsizei w, GLsizei h )
    void error_exit	( char *error_message )
    void usage		( char *name )
    static GLenum Key 	( int key, GLenum mask )
    void main 		( int argc, char** argv )
    void print_help()
	void InitParams()


============================================================================ */

#pragma warning (disable : 4244)	//added by KLL

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <GL/glut.h>	    /* OpenGl headers	- aadesche	     */

//yw changed! start
#include <GL/glaux.h>		// Header File For The Glaux Library - aadesche
//yw changed! end

#include "memory.h"               /* Local memory allocation macros          */
/* #include "window.h"               Local window header  */
#include "head.h"                 /* Local head data structure               */


/*added by Erika */
#include "camera.h"
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif

#define FACADE_FRAMERATE 30.0f  // hardcode the target framerate -- GCK 3/7/01

static int verbose = 0;

extern void initGLUI(int);    //  Added by GCK 3/3/01
extern void updateGUI(void);  //  Added by GCK 3/4/01

void print_mesg(void);
void print_help(void);
void reset(void);  // Added by Andrew 2-8-2003
void InitMatrix();  // Added by Andrew 2-8-2003
extern void updateParam();  // Added by Andrew 2-8-2003
float RotMatrix[4][4];	/* set by glui rotation widget. Added by Andrew 2-8-2003 */

int DRAW_MODE = 2 ;

//yw changed! start
int texture;
int useTexturing;
//yw changed! end

//Add by Victor chen
float face_specular = 1.0f;
float face_brightness = 0.7f;
//End by victor chen

static int spinxlight = 0 ;
static int spinylight = 0 ;
static int spinxface = 0 ;
static int spinyface = 0 ;

// added by Maureen for Lights
//int lightArray[6] = {1, 0, 1, 0, 0, 0};
int lightArray[6] = {1, 1, 1, 0, 0, 0};

GLfloat light_positions[6][4] = {
    {10.0, 5.5, 15.0, 0.0},             /*top, left front*/
    {10.0, 5.5, -15.0, 0.0},            /*side light top, right back*/
	{-10.0, -0.5, -15.0, 1.0},			/*botto, right front*/
    {-10.0, -0.5, 15.0, 1.0},           /*botto, left front*/
	{-10.0, 30, 15.0, 1.0},				/*top, left front*/
	{0, 5, -15.0, 1.0}					/*back*/
};

GLfloat white_light[] = { 1.0, 1.0, 1.0, 1.0 };

//
//by Victor
GLfloat side_light[] = {0.3,0.35,0.4,1.0};
GLfloat back_light[] = {0.9,0.8,0.8,1.0};
GLfloat gray_light[] = {0.6,0.6,0.6,1.0};
GLfloat light_ambient[] = {0.0,0.0,0.0,1.0};
//Victor//

/* pts on symetry line (x=0) */
g_sym[29] = {1,6,11,14,16,23,31,34,41,49,52,55,58,61,64,67,71,87,88,89,80,90,97,108,125,156,157,162,167 };


/* ========================================================================= */
/* motion	                                                             */
/* ========================================================================= */
/*
** Rotate the face and light about.
*/

//yw changed! start
//=================

AUX_RGBImageRec *LoadBMP(char *Filename)				// Loads A Bitmap Image
{
	FILE *File=NULL;									// File Handle

	if (!Filename)										// Make Sure A Filename Was Given
	{
		return NULL;									// If Not Return NULL
	}

	File=fopen(Filename,"r");							// Check To See If The File Exists

	if (File)											// Does The File Exist?
	{
		fclose(File);									// Close The Handle
		return auxDIBImageLoad(Filename);				// Load The Bitmap And Return A Pointer
	}

	return NULL;										// If Load Failed Return NULL
}

void LoadTexture(char* filename)
{
	AUX_RGBImageRec* TextureImage[1];

	TextureImage[0] = LoadBMP(filename);

	if (TextureImage[0] == NULL)
	{
		printf("File %s not found!\n", filename);
		useTexturing = 0;
		return;

	}

	glGenTextures(1, &texture);

	glBindTexture(GL_TEXTURE_2D, texture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexImage2D(GL_TEXTURE_2D, 0, 3,
				 TextureImage[0]->sizeX, TextureImage[0]->sizeY,
				 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
}

//yw changed! end
//===============

int rotate = 0, movelight = 0, origx, origy;

void motion ( int x, int y )
{
  if (rotate) {
    spinyface = ( spinyface + (x - origx) ) % 360 ;
    spinxface = ( spinxface - (y - origy) ) % 360 ;
    origx = x;
    origy = y;
    glutPostRedisplay();
  }
  if (movelight) {
    spinylight = ( spinylight + (x - origx ) ) % 360 ;
    spinxlight = ( spinxlight - (y - origy ) ) % 360 ;
    origx = x;
    origy = y;
    glutPostRedisplay();
  }
}

void
mouse(int button, int state, int x, int y)
{
  switch(button) {
  case GLUT_LEFT_BUTTON:
    if (state == GLUT_DOWN) {
      origx = x;
      origy = y;
      rotate = 1;
    } else {
      rotate = 0;
    }
    break;
  case GLUT_MIDDLE_BUTTON:
    if (state == GLUT_DOWN) {
      origx = x;
      origy = y;
      movelight = 1;
    } else {
      movelight = 0;
    }
    break;
  }
}


/* ========================================================================= */
/* myinit		                                                     */
/* ========================================================================= */
/*
** Do the lighting thing.
*/

void myinit ( void )
{
  glEnable    ( GL_LIGHTING   ) ;
  glEnable    ( GL_LIGHT0     ) ;
  glDepthFunc ( GL_LEQUAL     ) ;
  glEnable    ( GL_DEPTH_TEST ) ;
  //yw changed! start
  useTexturing = 0;
  //yw changed! end
}


/* ========================================================================= */
/* faceinit		                                                     */
/* ========================================================================= */
/*
** Read in the datafiles and glutInit(&argc, argv); initialize the face data structures.
*/

void
faceinit ( void )
{
int i,j;

//yw changed! start
FILE* infile;
int temp;
//yw changed! end

g_facetype=HUMAN;  /* init globals */
g_lbinc=1;
g_anim=0;
for (i=0;i<MAX_PT_POLY;i++)
   for (j=0;j<3;j++) {
       g_pt[i][j]=0.0;
       g_inpts[i][j]=0.0;
       g_interp[i][j]=0.0;
       g_pg[i][j]=0;
       }

	/*	read in data files				*/
  fprintf(stderr,"Reading face data");
  g_np=readpt(g_interp,"full2.pts"); /* read second vertices set */
  fprintf(stderr," . ");
  g_np=readpt(g_inpts,"full1.pts");  /* read first vertices set */
  fprintf(stderr,". ");
  g_ng=readt("full.top");          /* read topology file */
  fprintf(stderr,". ");

  //yw changed! start
  infile = fopen("full.tex", "r");

  for (i=0; i<g_ng; i++)
  {
	  fscanf(infile, "%d %f %f %f %f %f %f %f %f %f \n",
			 &temp, &tex[i][0][0], &tex[i][0][1], &tex[i][0][2],
			 &tex[i][1][0], &tex[i][1][1], &tex[i][1][2],
			 &tex[i][2][0], &tex[i][2][1], &tex[i][2][2]);
  }

  //yw changed! end

  fprintf(stderr,"done, %d points, %d polys\n",g_np,g_ng);

   memmove(g_pt,g_inpts,sizeof(g_pt));

  InitParams();	/* init param list */
  InitMatrix(); /* Added by Andrew 2-8-2003 */
  g_curframe=SetUpKeys();
  UpdateObject();

  }


/* Function by Maureen for Lighting
 * This function is called by display.  If goes through all the lights,
 * enabling them if the should be on or vice versa.
 */
void UpdateLights(void)
{
	int i;

	for(i = 0; i < 6; i++){
		if (lightArray[i]){
			switch(i)
			{
				case 0:
					glEnable    ( GL_LIGHT1     ) ;
					glLightfv( GL_LIGHT1, GL_POSITION, light_positions[0] ) ;
					glLightfv( GL_LIGHT1, GL_DIFFUSE, white_light ) ;
					glLightfv( GL_LIGHT1, GL_SPECULAR, white_light ) ;
					break;
				case 1:
					glEnable    ( GL_LIGHT2     ) ;
					glLightfv( GL_LIGHT2, GL_POSITION, light_positions[1] ) ;
                    glLightfv( GL_LIGHT2, GL_DIFFUSE, side_light ) ;
                    glLightfv( GL_LIGHT2, GL_SPECULAR, white_light ) ;
					break;
				case 2:
					glEnable    ( GL_LIGHT3     ) ;
					glLightfv( GL_LIGHT3, GL_POSITION, light_positions[2] ) ;
                    glLightfv( GL_LIGHT3, GL_DIFFUSE, back_light ) ;
					glLightfv( GL_LIGHT3, GL_SPECULAR, white_light ) ;
					break;
				case 3:
					glEnable    ( GL_LIGHT4     ) ;
					glLightfv( GL_LIGHT4, GL_POSITION, light_positions[3] ) ;
					glLightfv( GL_LIGHT4, GL_DIFFUSE, white_light ) ;
					glLightfv( GL_LIGHT4, GL_SPECULAR, white_light ) ;
					break;
				case 4:
					glEnable    ( GL_LIGHT5		) ;
					glLightfv( GL_LIGHT5, GL_POSITION, light_positions[4] ) ;
					glLightfv( GL_LIGHT5, GL_DIFFUSE, white_light ) ;
					glLightfv( GL_LIGHT5, GL_SPECULAR, white_light ) ;
					break;
				case 5:
					glEnable    ( GL_LIGHT6     ) ;
					glLightfv( GL_LIGHT6, GL_POSITION, light_positions[5] ) ;
					glLightfv( GL_LIGHT6, GL_DIFFUSE, white_light ) ;
					glLightfv( GL_LIGHT6, GL_SPECULAR, white_light ) ;
					break;
			}
		} else{
			switch(i)
			{
				case 0:
					glDisable(GL_LIGHT1);
					break;
				case 1:
					glDisable(GL_LIGHT2);
					break;
				case 2:
					glDisable(GL_LIGHT3);
					break;
				case 3:
					glDisable(GL_LIGHT4);
					break;
				case 4:
					glDisable(GL_LIGHT5);
					break;
				case 5:
					glDisable(GL_LIGHT6);
					break;
			}
		}
	}
}


/* ========================================================================= */
/* display                                                                   */
/* ========================================================================= */
/*
** Here's were all the display action takes place.
*/

void display ( void )
{
	  //GLfloat position [] = { 30.0, 70.0, -100.0, 1.0 }  ;
      GLfloat position [] = {   10.0, 5.0, -15.0, 0.0 }  ;

  GLfloat diffuseMaterial[4]= { 0.5, 0.5, 0.6, 1.0 };

  glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;


  /* added by Erika */
  UpdateCamera();

  /*added by Maureen*/
  UpdateLights();

  glPushMatrix ( ) ;

     glTranslatef ( 0.0, 0.0, -5.0 ) ;
	 glRotatef	(  180., 0.0, 1.0, 0.0 ) ;
	 glScalef  (1.4,1.4,1.4) ;


    glRotated	( (GLdouble) spinxface, 1.0, 0.0, 0.0 ) ;
    glRotated	( (GLdouble) spinyface, 0.0, 1.0, 0.0 ) ;
	glMultMatrixf ( (const GLfloat *) RotMatrix );

    glPushMatrix ( ) ;
      glRotated		( (GLdouble) spinxlight, 1.0, 0.0, 0.0 ) ;
      glRotated		( (GLdouble) spinylight, 0.0, 1.0, 0.0 ) ;
      glLightfv		( GL_LIGHT0, GL_POSITION, position ) ;
	  glMaterialfv  ( GL_FRONT,GL_DIFFUSE,diffuseMaterial);
      glTranslated 	( 0.0, 0.0, 50.0 ) ;
      glDisable		( GL_LIGHTING ) ;
      glEnable      ( GL_LIGHTING ) ;
   glPopMatrix ( ) ;


   /* ---------------->
   /*  Section rewritten by GCK 3/7/01  */
   /*  Chagned on 3.09.01 by GCK */
   if (g_anim)
   {
	   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	   StopTimer(animTimer);
	   anim_frame+=GetInterval(animTimer)*FACADE_FRAMERATE;
	   ReStartTimer(animTimer);

	   DrawFrame(anim_frame);

	   if ( anim_frame > (float) g_playTo ) // changed by GCK 3.09.01
	   {
		   g_curframe=g_playTo; // changed by GCK 3.09.01
		   anim_frame=(float) g_playFrom; // changed by GCK 3.09.01
		   g_anim=0;
		   if (g_curframe == g_keys[g_nkeys-1])
		   {
			   ReadKey(g_curframe);
			   UpdateObject();
		   }
		   //ReadKey(g_keys[g_nkeys-1]); UpdateObject();    //  bug rewritten, commented out by GCK 3.09.01
		   updateGUI();                                     //  added by GCK on 3/4/01
	   }
   }
   /* ---------------------> */

   comnor();   /* calculate common normals */
   vnorm(0);   /* calculate vertex normals */

   paint_polygons (DRAW_MODE) ;

   glPopMatrix();

   glutSwapBuffers();
}


/* ========================================================================= */
/* myReshape		                                                     */
/* ========================================================================= */
/*
** What to do of the window is modified.
*/

extern void jitter(GLdouble, GLdouble);  // GCK 3/11/01

void myReshape ( GLsizei w, GLsizei h )
{
  g_width = w;
  g_height = h;
  glViewport	( 0,0,w,h ) ;
  jitter(0,0);  // changed by GCK 3/11/01
}


/* ========================================================================= */
/* error_exit	                                                             */
/* ========================================================================= */
/*
** Problems!
*/

void error_exit( char *error_message )
{
    fprintf ( stderr, "%s\n", error_message ) ;
    exit( 1 ) ;
}


/* ========================================================================= */
/* usage		                                                     */
/* ========================================================================= */
/*
** At startup provide usage modes.
*/

void usage( char *name )
{
    fprintf( stderr, "\n%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
        "usage: ", name, " [options]\n\n",
        "  Options:\n",
        "    -display  displayname  specify an X server connection\n",
        "    -geometry geometry     specify window geometry in pixels\n",
        "    -rgba                  ask for rgba visual\n",
        "    -index                 ask for color index visual\n",
        "    -doublebuffer          ask for double buffered visual\n",
        "    -singlebuffer          ask for single buffered visual\n",
        "    -accum                 ask for accumulation buffer\n",
        "    -alpha                 ask for alpha buffer\n",
        "    -depth                 ask for depth buffer\n",
        "    -stencil               ask for stencil buffer\n",
        "    -aux nauxbuf           specify number of aux buffers\n",
        "    -level planes          specify planes (0=main,>0=overlay,<0=underlay\n",
        "    -transparent           ask for transparent overlay\n",
        "    -opaque                ask for opaque overlay\n"
    );

    exit( 1);
}

/*added by Maureen
 * This is called by Key function, to check if the input string disables or enables
 * lights.
 */
int CheckLights(char* line)
{
	switch(line[0])
	{

		case '0':
			lightArray[0] = (lightArray[0] == 0) ? 1 : 0;
			return(1);
		case '1':
			lightArray[1] = (lightArray[1] == 0) ? 1 : 0;
			return(1);
		case '2':
			lightArray[2] = (lightArray[2] == 0) ? 1 : 0;
			return(1);
		case '3':
			lightArray[3] = (lightArray[3] == 0) ? 1 : 0;
			return(1);
		case '4':
			lightArray[4] = (lightArray[4] == 0) ? 1 : 0;
			return(1);
		case '5':
			lightArray[5] = (lightArray[5] == 0) ? 1 : 0;
			return(1);
		default: return (0);
	}
}


/* ========================================================================= */
/* Key			                                                     */
/* ========================================================================= */
/*
** Actions on a key press.
*/

static int m = 0, e = 0;
static char gInputLine[512];
static char* gInputLinePtr = gInputLine;
#define kReturn 0xd
#define kDelete 0x7f
extern void KeyBoard(char* line);

/* ARGSUSED1 */
static void Key ( unsigned char key, int x, int y )
{
	int isLight = 0;	//Maureen
	switch (key)
	{
		case kReturn:
			*gInputLinePtr = '\0';
			gInputLinePtr = gInputLine;
			printf(" - ");

			/*added by Maureen*/
			isLight = CheckLights(gInputLine);
            //

			if(!isLight) KeyBoard(gInputLine);

			printf("\n");

			break;

		case kDelete:
			printf("\b");
			printf(" ");

			if (gInputLinePtr != gInputLine)
			{
				--gInputLinePtr;
				*gInputLinePtr = '\0';
			}

			printf("\r%s", gInputLine);
			break;

		default:
			*gInputLinePtr++ = (char)key;
			printf("%c", (char)key);
			break;
	}
}

/* Function rewritten by Erika  */
void
special(int key, int x, int y)
{
	double S;
	double g_rad = 5;
	double g_phi = 0;
	double g_theta = 0;


	//char title[512];

	if (g_camera) {
	g_rad = sqrt(g_eyex * g_eyex + g_eyey * g_eyey + (g_eyez+5) * (g_eyez+5));
	g_phi = acos(g_eyey / g_rad);
	S = sqrt((g_eyez+5) * (g_eyez+5) + g_eyex * g_eyex);

	if ((g_eyez+5) >= 0)
		g_theta = asin(g_eyex / S);
	else
		g_theta = M_PI - asin(g_eyex / S);

	switch(key) {
	case GLUT_KEY_END:

		//glutSetWindowTitle(title);
		g_fovy = g_fovy - 0.1;
		break;
	case GLUT_KEY_PAGE_DOWN:
		//glutSetWindowTitle(title);
		g_fovy = g_fovy + 0.1;
		break;
	case GLUT_KEY_RIGHT:


		g_theta = g_theta + 0.05;

		break;
	case GLUT_KEY_LEFT:

		//glutPostRedisplay();
		g_theta = g_theta - 0.05;
		break;

	case GLUT_KEY_DOWN:
		if (g_phi < M_PI - 0.05) g_phi = g_phi + 0.05;
		break;

	case GLUT_KEY_UP:
		if (g_phi > 0.05) g_phi = g_phi - 0.05;
		break;

	case GLUT_KEY_HOME:
		g_rad = g_rad + 0.05;
		break;

	case GLUT_KEY_PAGE_UP:
		if (g_rad > 0.05) g_rad = g_rad - 0.05;
		break;

	}

	g_eyez = g_rad * sin(g_phi) * cos(g_theta) - 5;
	g_eyex = g_rad * sin(g_phi) * sin(g_theta);
	g_eyey = g_rad * cos(g_phi);

	}

}




void
main_menu_select(int value)
{

  switch(value) {
  case 1:
    reset();
    glutPostRedisplay();
    break;
  case 2:
    print_help();
    break;
  case 3:
    glutPostRedisplay();
    break;
  case 4:

    glutPostRedisplay();
    break;
  case 5:

    break;
  case 6:

	glutPostRedisplay();

    break;
  case 666:
    exit(0);
    break;
  }
}

void
draw_mode_select(int value)
{
  DRAW_MODE = value;
  glutPostRedisplay();
}


void
make_menus(void)
{
  int  draw_mode_menu;

  /*
  char *entry;

  muscle_menu = glutCreateMenu(muscle_select);
  for (i=0; i<face->nmuscles; i++) {
    entry = face->muscle[i]->name;
    for(j=(int) strlen(entry)-1; j>=0; j--) {
      if (entry[j] == '_') entry[j] = ' ';
    }
    glutAddMenuEntry(entry, i);
  }
  */
  draw_mode_menu = glutCreateMenu(draw_mode_select);
  glutAddMenuEntry("Wireframe", 0);
  glutAddMenuEntry("Polygonal patches", 1);
  glutAddMenuEntry("Smooth surface", 2);
  glutCreateMenu(main_menu_select);
  glutAddSubMenu("Draw mode", draw_mode_menu);
  glutAddMenuEntry("Face reset", 1);
  glutAddMenuEntry("Print help", 2);
  glutAddMenuEntry("Quit", 666);
  glutAttachMenu(GLUT_RIGHT_BUTTON);
}

/* ========================================================================= */
/* main			                                                    */
/* ========================================================================= */
/*
** All the initialization and action takes place here.
*/

int main ( int argc, char** argv )
{
  int i, w;
  char* deletefaskeys = "del fas.keys";

  system(deletefaskeys); // cleanup
//  g_width = 400;  // gck 3.09.01
//  g_height = 600; // gck 3.09.01
  glutInitWindowSize	( 400, 600 ) ;
  glutInit(&argc, argv);
  for(i=1; i<argc; i++) {
    if(!strcmp(argv[i], "-v")) {
      verbose = 1;
    }
  }

  glutInitDisplayMode	(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
  w = glutCreateWindow		( "facade" ) ;
  myinit		( ) ;
  faceinit		( ) ;
  glutMouseFunc(mouse);
  glutMotionFunc(motion);
  glutKeyboardFunc		( Key ) ;
  glutSpecialFunc(special);
  glutReshapeFunc 	( myReshape ) ;

  glutDisplayFunc(display);

  anim_frame = 0.0f;
  animTimer = (HighPerformanceTimer*) malloc(sizeof(HighPerformanceTimer));
  TimerInit(animTimer);

  pixdx = pixdy = 0.0;  // GCK 3.11.01

  g_interpMode = LINEAR; // GCK 03.09.01
  g_sndFileName = NULL;
  initGLUI(w);
//  glutIdleFunc(display);

  /*added by Erika */
  InitCamera();

  make_menus();
  glutMainLoop() ;
  return 0;             /* ANSI C requires main to return int. */
}

void
InitParams()
{
int i,j;
   ipm=ipml; cpm=cpml; bpm=bpml;
   for (i=0;i<2;i++) {

      ipm[1] = .9;	/* eye opening (0.0<=>1.0)	*/
      ipm[2] = .0;	/* eyebrow tip */
      ipm[3] = .0;	/* BLANK eyebrow separation(0.0<=>25.0)*/
      ipm[4] = 0.0;	/*  jaw rotation (0.0<=>20.0)	*/
      ipm[5] = 1.0;	/* eyelid X scale		*/
      ipm[6] = 1.0;	/* eyelid Y scale		*/
      ipm[7] = .0;	/* eyebrow center (hair)  		*/
      ipm[8] = .0;	/* eyebrow range (hair)		*/
      ipm[9] = .0;	/* eyebrow move Y  (hair)	*/
      ipm[10]= 1.0;	/*  nose tip X scale		*/
      ipm[11]= 1.0;	/* nose bridge X scale		*/
      ipm[12]= 1.0;	/* mouth X scale		*/
      ipm[13]= 1.0;	/* BLANK nostril scale 		*/
      ipm[14]=  .0;	/* mouth Z offset		*/
      ipm[15]=  .0;	/* lip thickness 			*/
      ipm[16]=  .0;	/* middle lip move x 	*/
      ipm[17]=  .0;	/* middle lip move y 	*/
      ipm[18]=  .0; 	/* eye move x 	*/
      ipm[19]= 1.0;	/*  jaw X scale			*/
      ipm[20]= 1.0;	/*  cheek X scale		*/
      ipm[21]=  .0;	/* BLANK lower lip 'f' tuck		*/
      ipm[22]=  .0;	/* raise upper lip		*/
      ipm[23]=  .0;	/* hair chin stretch (y move)	*/
      ipm[25]=  .0;	/* BLANK forehead interpolation	*/
      ipm[26]=  .0;	/* nose tip Z offset		*/
      ipm[27]=  .0;	/* nose tip Y offset		*/
      ipm[28]=  .0;	/* BLANK cheekbone interpolation	*/
      ipm[29]=  .0;	/* BLANK cheek hollow interpolation	*/
      ipm[30]=  .0;	/* BLANK chin interpolation		*/
      ipm[31]=  .0;	/* chin Z offset		*/
      ipm[32]=  .0;	/* chin Y offset		*/
      ipm[33]=  1.0;    /* neck scale			*/
      ipm[34]=  .0;	/* eyebrow Y offset		*/
      ipm[35]= 1.0;	/* chin to mouth scaling(Y)	*/
      ipm[36]= 1.0;	/* chin to eye scaling(Y)	*/
      ipm[37]= 1.0;	/* skew head  		*/
      ipm[40]= 1.0;	/* neck xy scale */
      ipm[41]= 2.0;	/* head left cut offset */
      ipm[42]= -2.0;	/* head right cut offest */
      ipm[45]= .135;	/* eyelid radius		*/
      ipm[46]= 0.0;	/* BLANK growth factor		*/
      ipm[47]= 0.0;	/* teeth move x 		*/
      ipm[48]= 0.0;	/* teeth move y			*/
      ipm[49]= 0.0;	/* teeth move z			*/
      ipm[50]= 1.0;	/* shading (1.=smooth,0.0=faceted)*/
      ipm[51]= 0.0;	/* pupil y rotation 		*/
      ipm[52]= 0.0;	/* pupil x rotation 		*/
      ipm[53]= 0.0;	/* neck y offset 		*/
      ipm[54]= 0.0;	/* rot neckx  			*/
      ipm[55]= 0.0;	/* rot necky 			*/
      ipm[56]= 0.0;	/* rot neckz 			*/
      ipm[57]= 1.0;	/* squash and stretch x 	*/
      ipm[58]= 1.0;	/* top of head scale  		*/
      ipm[59]= 1.0;	/* top of head cutoff  		*/
      ipm[61]= 0.0;	/* blank          	 	*/
      ipm[62]= 0.0;	/* top lip mv x       	 	*/
      ipm[63]= 0.0;	/* lip corner x      	 	*/
      ipm[64]= 0.0;	/* lip corner y       	 	*/
      ipm[65]= 0.0;	/* lip corner z			*/
      ipm[66]= 0.0;	/* top lip inner mv x  	 	*/
      ipm[67]= 0.0;	/* top lip inner mv y  	 	*/
      ipm[68]= 0.0;	/* top lip inner mv z  	 	*/
      ipm[69]= 0.0;	/* top lip outter mv x 	 	*/
      ipm[70]= 0.0;	/* top lip outter mv y 	 	*/
      ipm[71]= 0.0;	/* top lip outter mv z 	 	*/
      ipm[72]= 0.0;	/* top lip "o" shape   	 	*/
      ipm[73]= 0.0;	/* bot lip "o" shape   	 	*/
      ipm[74]= 0.0;	/* top lip mv z       	 	*/
      ipm[75]= 0.0;	/* bot lip mv z       	 	*/
      ipm[76]= 0.0;	/* bot lip middle mv x 	 	*/
      ipm[77]= 0.0;	/* bot lip inner mv x 	 	*/
      ipm[78]= 0.0;	/* bot lip outter mv x 	 	*/
      ipm[79]= 0.0;	/* smile 			*/
      ipm[80]= 0.0;	/* head 			*/
      ipm[81]= 0.0;	/* */
      ipm[82]= 0.0;	/* */
      ipm[83]= 0.0;	/* */
      ipm[84]= 0.0;	/* */
      ipm[85]= 0.0;	/* */
      ipm[86]= 0.0;	/* */
      ipm[87]= 0.0;	/* mouth 			*/
      ipm[88]= 0.0;	/* */
      ipm[89]= 0.0;	/* */
      ipm[90]= 0.0;	/* */
      ipm[91]= 0.0;	/* */
      ipm[92]= 0.0;	/* */
      ipm[93]= 0.0;	/* */
      ipm[94]= 0.0;	/* */
      ipm[95]= 0.0;	/* */
      ipm[96]= 0.0;	/* */
      ipm[97]= 0.0;	/* */
      ipm[98]= 0.0;	/* */
      ipm[99]= 0.0;	/* */
      ipm[100]= 1.0;	/* scale teeth x*/
      ipm[101]= 1.0;	/* */
      ipm[102]= 0.0;	/*    warps warps warps*/
      ipm[103]= 0.0;	/*    warps warps warps*/
      ipm[104]= 0.0;	/*    warps warps warps*/
      ipm[105]= 0.0;	/*    warps warps warps*/
      ipm[106]= 0.0;	/*    warps warps warps*/
      ipm[107]= 0.0;	/*    warps warps warps*/
      ipm[108]= 0.0;	/*    warps warps warps*/
      ipm[109]= 0.0;	/*    warps warps warps*/
      ipm[110] = 0.0;
      ipm[111] = 0.0;
      ipm[112] = 0.0;
      ipm[113] = 0.0;
      ipm[114] = 0.0;
      ipm[115] = 0.0;
      ipm[116] = 0.0;
      ipm[117] = 0.0;
      ipm[118] = 0.0;
      ipm[119] = 0.0;
      ipm[120] = 0.0;
      ipm[121] = 0.0;
      ipm[122] = 0.0;
      ipm[123] = 0.0;
      ipm[124] = 0.0;
      ipm[125] = 0.0;
      ipm[126] = 0.0;
      ipm[127] = 0.0;
      ipm[128] = 0.0;
      ipm[129] = 0.0;
      ipm[130] = 0.0;
      ipm[131] = 0.0;
      ipm[132] = 0.0;
      ipm[133] = 0.0;
      ipm[134] = 0.0;
      ipm[135] = 0.0;
      ipm[136] = 0.0;
      ipm[137] = 0.0;
      ipm[138] = 0.0;
      ipm[139] = 0.0;
      ipm[140] = 0.0;
      ipm[141] = 0.0;
      ipm[142] = 0.0;
      ipm[143] = 0.0;
      ipm[144] = 0.0;
      ipm[145] = 0.0;
      ipm[146] = 0.0;
      ipm[147] = 0.0;
      ipm[148] = 0.0;
      ipm[149] = 0.0;
      ipm[150] = 0.0;
      ipm[151] = 0.0;
      ipm[152] = 0.0;
      ipm[153] = 0.0;
      ipm[154] = 0.0;
      ipm[155] = 0.0;
      ipm[156] = 0.0;
      ipm[157] = 0.0;
      ipm[158] = 0.0;
      ipm[159] = 0.0;
      ipm[160] = 0.0;
      ipm[161] = 0.0;
      ipm[162] = 0.0;


   memmove(bpm,ipm,sizeof(bpmr));
   memmove(cpm,ipm,sizeof(cpmr));
   for (j=1;j<MAXPM;j++) bpm[j]+=.0001;
   bpm=bpmr; cpm=cpmr; ipm=ipmr;
   }
}

/* Added by Andrew 2-3-2003 */
 void reset()
 {
	 InitParams();
	 InitMatrix();
	 DRAW_MODE = 2;
	 UpdateObject();
	 updateParam();
 }

/* Added by Andrew 2-8-2003 */
 void InitMatrix()
 {
	RotMatrix[0][1] = RotMatrix[0][2] = RotMatrix[0][3] = 0.;
	RotMatrix[1][0] = RotMatrix[1][2] = RotMatrix[1][3] = 0.;
	RotMatrix[2][0] = RotMatrix[2][1] = RotMatrix[2][3] = 0.;
	RotMatrix[3][0] = RotMatrix[3][1] = RotMatrix[3][3] = 0.;
	RotMatrix[0][0] = RotMatrix[1][1] = RotMatrix[2][2] = RotMatrix[3][3] = 1.;
 }


 void print_help()
	{
              printf("			KEYFRAME COMMANDS\n");
              printf("r <frame #> -- Read frame (or i)");
              printf("\t> <  -- incr/decr through key frames\n");
              printf("d <key #> -- Delete key");
              printf("\t\t\t+ -  -- incr/decr through frames\n");
              printf("w <key #> -- Write out key");
              printf("\t\tk -- print all Keys\n");
	          printf("sk <nlf> <ff> <lf> -- Scale Keys firstf-lastf to firstf-newlastf\n");
              printf("			PARAMETER COMMANDS\n");
              printf("p{rl} <pnum> [pvalue] -- Param value: display or change (left,right or both\n");
       	      printf("l{rw} <entry> [region] -- Read/Write Library Entry, region: m - mouth, e - eyes\n");
              printf("pw <lowkey> <highkey> <pnum> <leftval> <rghtval> -- write param to set of keys\n");
              printf("pi <lowkey> <highkey> <pnum> - Interp a specific param over a set of keys\n");
              printf(". (dot) -- undo current parameter change \n");
              printf("			PLAYBACK COMMANDS\n");
              printf("P -- Playback animation\n");
			  printf("le <lipsync file> -- Enable lipsyncing");
		      printf("\tld -- disable lipsyncing\n");
              printf("			DISPLAY COMMANDS\n");
              printf("ov -- Vector output");
              printf("\t\t\tof -- Facet shaded output\n");
              printf("os -- Smooth shaded output");
			  printf("\t\t1-5 -- turn on/off light 1-5\n");
			  printf("t <texture file> -- texture output");
			  printf("\ttd -- Disable texture mapping\n");
              printf("			MISCELLEOUS COMMANDS\n");
              printf("q -- Quit");
              printf("\t\t\t\t? or h -- help message\n");
	          printf("a{rw} <file name>  -- reads writes Animation file (all keys)\n");
	}



