/* ==========================================================================
                            EYES.C
=============================================================================

    DESCRIPTION
    This module has eye based face parameter routines. Works with params.c which has
	the main face param calling routine as well as other face params and mouth.c which
	has the mouth parameter routines. See the InitParams for an explanation of the specific
	eye params. There alot of funky magic code in here!

    HISTORY
	1/01   steve dipaola    ported from SGI via GLUT example files


    FUNCTION NAMES


    C SPECIFICATIONS


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

#include "head.h"
#include "p3.h"
#include "math.h"

void eyescale(int off,int i,float frac);
void eyescalelocal(int off,int i,float frac,int x,int y,int z);
void readeb(int off);
void writeeb(int off);

#define MAXEB 7
#define HALFEB ((MAXEB-1)/2.0)
float eb[MAXEB][3];

/*	eye mapping			*/
void eyes(int off)
{
   int i,j,axis=2,off2;
   float eyerad,eps=0.0,len,eyesc[3];
   double CTM[4][4],angle,dpt[3];
eyerad=cpm[45];
eyesc[0]=cpm[5]; eyesc[1]=cpm[6]; eyesc[2]=1.;
/* straighten eyes horizontally (rot z) for eyelid scale */
if (off) angle= 9.; else angle= -8.;
l3d_ident(CTM);
l3d_rot(CTM,RADIANS(angle),axis);
eps = 1.09;
if (off) off2=100; else off2=0;

   for (i=172+off; i<=222+off; i++) {
      if (i>=207+off && i<=221+off) eps = 1.18; else eps = 1.09;
      for (j=0; j<3; j++) {
     		/* interpolate eyelid between open(1) & close(0) */
         g_pt[i][j] = (cpm[1]*g_inpts[i][j]+(1.-cpm[1])*g_interp[i][j]);
  		/* translate from face coord. to eye coord. */
         g_pt[i][j] -= g_inpts[295+off][j];
      }
	  /* straighten eyes horizontally (rot z) */
	  /*
      if (g_facetype!=HUMAN) {
     for (j=0; j<3; j++)  dpt[j]=g_pt[i][j];
     l3d_xformd(CTM,dpt,dpt); 
     for (j=0; j<3; j++)  g_pt[i][j]=dpt[j];
     }
      */

  		/* legth of vector */
     len = sqrt(g_pt[i][0]*g_pt[i][0]+g_pt[i][1]*g_pt[i][1]+g_pt[i][2]*g_pt[i][2]);
 		/* map pts on sphere */
     for (j=0; j<3; j++) g_pt[i][j] = (((eyerad*eyesc[j])*eps)/len)*g_pt[i][j];
  		/* translate from eye coord. to face coord. */
     for (j=0; j<3; j++) g_pt[i][j] += g_inpts[296+off][j];
   }


 /* above the eye scaling */
 if (eyesc[0]>1. || eyesc[1]>1.) {
    for (i=138+off; i<=143+off; i++) eyescale(off,i,.5);
    for (i=144+off; i<=148+off; i++) eyescale(off,i,.45);
    for (i=288+off; i<=292+off; i++) eyescale(off,i,.4);
    for (i=150+off; i<=155+off; i++) eyescale(off,i,.4);
    for (i=160+off; i<=161+off; i++) eyescale(off,i,.3);
    for (i=165+off; i<=166+off; i++) eyescale(off,i,.16);
     eyescale(off,149+off,.005);
     eyescale(off,163+off,.006);
     eyescale(off,164+off,.017);
     eyescale(off,157+off,.01);
     eyescale(off,158+off,.03);
     eyescale(off,159+off,.25);
    /*for (i=169+off; i<=171+off; i++) eyescale(off,i,.05);*/
 /* below the eye scaling */
    for (i=129+off; i<=134+off; i++) eyescale(off,i,.4);
    eyescale(off,135+off,.4);
    eyescale(off,136+off,.3);
    eyescale(off,119+off,.46);
    for (i=120+off; i<=121+off; i++) eyescale(off,i,.3);
    eyescale(off,122+off,.25);
    eyescale(off,123+off,.2);
    eyescale(off,124+off,.1);
    for (i=111+off; i<=117+off; i++) eyescale(off,i,.25);
    for (i=101+off; i<=107+off; i++) eyescale(off,i,.17);
 }
/*    for (j=0; j<3; j++)
       g_pt[113+off][j]=((g_pt[119+off][j]+g_pt[102+off][j])/2.0);
       */


 /* move eyes in x */
if (cpm[18]!=0.0) {
for (i=172+off; i<=222+off; i++)
   g_pt[i][0]=g_pt[i][0]+cpm[18];
for (i=295+off; i<=296+off; i++)
   g_pt[i][0]=g_pt[i][0]+cpm[18];
}


       /* eye ball position and scale and rot */
l3d_ident(CTM);
l3d_scale(CTM,(float)(eyesc[0]),(float)(eyesc[1]),(float)(eyesc[2]));
l3d_rot(CTM,RADIANS((float)angle),2);
l3d_rot(CTM,RADIANS((float)cpm[52]*(eyesc[0]/2.2)),0); /* load rots for pupils */
l3d_rot(CTM,RADIANS((float)cpm[51]*(eyesc[1]/2.2)),1);
l3d_scale(CTM,(float)(eyerad),(float)(eyerad),(float)(eyerad));
  for (i=1501+off2; i<=1570+off2; i++) {
     for (j=0; j<3; j++)  dpt[j]=g_pt[i][j];
     l3d_xformd(CTM,dpt,dpt);
     for (j=0; j<3; j++) {
     g_pt[i][j]=dpt[j];
     g_pt[i][j] += g_pt[296+off][j];
     }
   }
}

void eyescale(int off,int i,float frac)
{
int j;
float eyesc[2];
eyesc[0]=cpm[5]; eyesc[1]=cpm[6];

  for (j=0; j<2; j++) {
     g_pt[i][j]-=g_pt[295+off][j];
     g_pt[i][j]*=(((eyesc[j]-1.)*frac)+1);
     g_pt[i][j]+=g_pt[296+off][j];
  }
}


void eyescalelocal(int off,int i,float frac,int x,int y,int z)
{
int j;
float eyesc[2];
eyesc[0]=cpm[5]; eyesc[1]=cpm[6];

if (x) {
     j=0;
     g_pt[i][j]-=g_pt[295+off][j];
     g_pt[i][j]*=(((eyesc[j]-1.)*frac)+1);
     g_pt[i][j]+=g_pt[296+off][j];
  }
if (y) {
     j=1;
     g_pt[i][j]-=g_pt[295+off][j];
     g_pt[i][j]*=(((eyesc[j]-1.)*frac)+1);
     g_pt[i][j]+=g_pt[296+off][j];
  }
if (z) {
     j=2;
     g_pt[i][j]-=g_pt[295+off][j];
     g_pt[i][j]*=(((eyesc[j]-1.)*frac)+1);
     g_pt[i][j]+=g_pt[296+off][j];
  }
}

   	/*	move eyebrows in Y	*/

void sub34(int off)
{
   int i;
  if (cpm[34]!=ipm[34]) {
   	for (i=144+off; i<=155+off; i++)
   	   g_pt[i][1]=g_pt[i][1]+cpm[34];
   	for (i=288+off; i<=292+off; i++)
   	   g_pt[i][1]=g_pt[i][1]+cpm[34];
	   }
}

void readeb(int off)
{
eb[0][0]=g_pt[149+off][1]; eb[0][1]=g_pt[149+off][1]; eb[0][2]=g_pt[149+off][1];
eb[1][0]=g_pt[150+off][1]; eb[1][1]=g_pt[288+off][1]; eb[1][2]=g_pt[144+off][1];
eb[2][0]=g_pt[151+off][1]; eb[2][1]=g_pt[289+off][1]; eb[2][2]=g_pt[145+off][1];
eb[3][0]=g_pt[152+off][1]; eb[3][1]=g_pt[290+off][1]; eb[3][2]=g_pt[146+off][1];
eb[4][0]=g_pt[153+off][1]; eb[4][1]=g_pt[291+off][1]; eb[4][2]=g_pt[147+off][1];
eb[5][0]=g_pt[154+off][1]; eb[5][1]=g_pt[292+off][1]; eb[5][2]=g_pt[148+off][1];
eb[6][0]=g_pt[155+off][1]; eb[6][1]=g_pt[155+off][1]; eb[6][2]=g_pt[155+off][1];
}


void writeeb(int off)
{
g_pt[149+off][1]=eb[0][0];
g_pt[150+off][1]=eb[1][0]; g_pt[288+off][1]=eb[1][1]; g_pt[144+off][1]=eb[1][2];
g_pt[151+off][1]=eb[2][0]; g_pt[289+off][1]=eb[2][1]; g_pt[145+off][1]=eb[2][2];
g_pt[152+off][1]=eb[3][0]; g_pt[290+off][1]=eb[3][1]; g_pt[146+off][1]=eb[3][2];
g_pt[153+off][1]=eb[4][0]; g_pt[291+off][1]=eb[4][1]; g_pt[147+off][1]=eb[4][2];
g_pt[154+off][1]=eb[5][0]; g_pt[292+off][1]=eb[5][1]; g_pt[148+off][1]=eb[5][2];
g_pt[155+off][1]=eb[6][0];
}

void eyebrows(int off)
{
int i,j;
float ebcenter,ebtip;
float eboff,ebrange,ebe[MAXEB],per;

  if (cpm[2]!=ipm[2] || cpm[7]!=ipm[7] || cpm[8]!=ipm[8] || cpm[9]!=ipm[9]) {
readeb(off);

ebcenter=(cpm[7]*MAXEB);
ebrange=cpm[8];
eboff=cpm[9];
ebtip=cpm[2];

for (i=0;i<MAXEB;i++)  {
 /* get percentage to skew data based on center pt as middle */
 if (i>=ebcenter) per=(float)(i-ebcenter)/(float)((MAXEB-1)-ebcenter+.00001);
 else per=(float)(i-ebcenter)/ebcenter;
    /* set up cos curve, ebrange is width,per is skewing */
    ebe[i] = pow(.5 + (.5 * cos(PI * (per))),ebrange);
    /* increase amplitude ofboundary cases */
    /*if (i==0 || i==MAXEB-1) ebe[i] *= 1.3;*/
    }

/* change eyebrow pts */
for (i=0;i<MAXEB;i++)
   for (j=0;j<3;j++)
       eb[i][j]= eb[i][j] + (eboff*ebe[i]);

/* eyebrow tip */
/*
for (i=0;i<(MAXEB/3);i++)
   for (j=0;j<3;j++)
       eb[i][j]= eb[i][j] + (ebtip*(1.-(i/(float)(MAXEB/3.))));
       */
       eb[0][0]= eb[0][0] + (ebtip);
       eb[1][0]= eb[1][0] + (ebtip * .6);
       eb[1][1]= eb[1][1] + (ebtip * .6);
       eb[1][2]= eb[1][2] + (ebtip * .6);

writeeb(off);
}
}
