/* ==========================================================================
                            PARAMS.C
=============================================================================

    DESCRIPTION
    This module has the main face parameter and the non-mouth and non-eye parameter
	routines. Calls eyes.c which has the eye params and mouth.c which has the mouth
	parameter routines. See the InitParams for an explanation of the specific params.
	There alot of funky magic code in here! Params effect pts of face directly.

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


    FUNCTION NAMES
	UpdateObject() - main param routine.

    C SPECIFICATIONS
	void UpdateObject()

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

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "head.h"
#include "p3.h"
#include <math.h>
#define HEADOFF .1

void move23(int beg,int end,float tap,int off);
void sub58a(int beg,int end);
void movep(int tpm,int tpt,int beg,int end,float tap,int off);
void scalep(int tpm,int tpt,int beg,int end,float tap,int off);

void
UpdateObject()

{
int off,doeyes,dobrows;


   memmove(g_pt,g_inpts,sizeof(g_pt));
   bpm=bpml; ipm=ipml; cpm=cpml;
   for (off=0;off<301;off=off+300) {
   doeyes=0;
   dobrows=0;
    /* if (!off) sub61(); lerp between heads  */
   eyes(off);
    sub58(off);
   sub31(off);
   sub32(off);
   sub33(off);
   sub14(off);
   sub12(off);
   sub15(off);
   sub35(off);
   sub36(off);
    sub4(off);
   sub34(off);
   eyebrows(off);
   sub26(off);
   sub27(off);
   sub10(off);
   sub11(off);
   /* sub13(off); */
   sub53(off);
   sub16(off);
   sub17(off);
   sub19(off);
   sub20(off);
   sub62(off);
   sub63(off);
   sub64(off);
   sub65(off);
   sub66(off);
   sub67(off);
   sub68(off);
   sub69(off);
   sub70(off);
   sub71(off);
   sub72(off);
   sub73(off);
   sub74(off);
   sub75(off);
   sub76(off);
   sub77(off);
   sub78(off);
   sub79(off);
   sub54(off);
   sub55(off);
   sub56(off);
   sub57(off);
   sub37(off);
    sub40(off);
    teeth(off);
    /* if (off) warpface(); */
   memmove(bpm,cpm,sizeof(bpmr));
   bpm=bpmr;ipm=ipmr;cpm=cpmr;
  }
}


/*		*** sympts ***			*/
/* - average together pts on symetry line (x=0) */
/*  and store new value in rightface pts        */

sympts()
{
   int i, j;

   for (i=0; i<SYMMAX; i++)
      for (j=0; j<3; j++)
         g_pt[g_sym[i]][j] = ( g_pt[g_sym[i]][j] + g_pt[g_sym[i]+300][j] ) * .5;
}

/*
 *****************  HEAD  **********************************
*/

#define	 fxx(x) (((amount*x*x*x)-(2.0*amount*x*x)+((amount+1.0)*x)))
#define	 dfxx(x) (((amount*x*x)-(2.0*amount*x)+(amount+1.0)))
#define	 fx(x) (((amount*(x-2.0)*x + (amount+1.0))*x))
#define	 dfx(x) (((amount*x-(2.0*amount))*x + amount+1.0))
#define	 tdfx(x) (((x-2.0)*x + 1.0))

escher(int off)

{
int i;
float	centerx, centery, centerz;
float	twist, amount;
float	radsqrx, radsqry, radsqrz;
amount=cpml[102];
centerx=cpml[103];
centery=cpml[104];
centerz=cpml[105];
radsqrx=cpml[106];
radsqry=cpml[107];
radsqrz=cpml[108];
twist=cpml[109];
   for (i=1+off; i<=296+off; i++)  {
if (amount) eschverts(i,amount,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
if (twist) twistverts(i,twist,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
}
  if (off) for (i=601; i<=1670; i++) {
if (amount) eschverts(i,amount,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
if (twist) twistverts(i,twist,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
}
/*
amount=cpmr[102];
centerx=cpmr[103];
centery=cpmr[104];
centerz=cpmr[105];
radsqrx=cpmr[106];
radsqry=cpmr[107];
radsqrz=cpmr[108];
twist=cpmr[109];
   for (i=1+off; i<=296+off; i++) {
if (amount) eschverts(i,amount,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
if (twist) twistverts(i,twist,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
}
   for (i=1; i<=1670; i++) {
if (amount) eschverts(i,amount,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
if (twist) twistverts(i,twist,centerx,centery,centerz,radsqrx,radsqry,radsqrz);
}
*/
}

eschverts(int i,float amount,float centerx,float centery,float centerz,float radsqrx,float radsqry,float radsqrz)
{
	float	fval, rr, dx, dy, dz;

    dx = g_pt[i][0] -centerx;   dy = g_pt[i][1]-centery; dz = g_pt[i][2]-centerz;
    rr = sqrt((dx*dx/radsqrx)+(dy*dy/radsqry)+(dz*dz/radsqrz));
    if (rr <= 1.0) {   /* inside the elipse */
		fval = dfx(rr);
		g_pt[i][0] = dx * fval + centerx;
		g_pt[i][1] = dy * fval + centery;
		g_pt[i][2] = dz * fval + centerz;
    }
	return 1;
}


twistverts(int i,float twist,float centerx,float centery,float centerz,float radsqrx,float radsqry,float radsqrz)
/* twist about z axis */
{
    float	rr, dx, dy, dz, ang,sine,cose;

    dx = g_pt[i][0] -centerx;   dy = g_pt[i][1]-centery; dz = g_pt[i][2]-centerz;
    rr = sqrt((dx*dx/radsqrx)+(dy*dy/radsqry)+(dz*dz/radsqrz));

    if (rr <= 1.0) {   /* inside the elipse */
		ang = twist * tdfx(rr);
		sine = sin(ang);
		cose = cos(ang);
		g_pt[i][0] = (dx*cose - dy*sine) + centerx;
		g_pt[i][1] = (dx*sine + dy*cose) + centery;
    }
	return 1;
}

   	/*  interp between full heads */
	/*
sub61(int off)

{
   int i,j;
   if (cpm[61]!=0.0) {
   for (i=1; i<=1500; i++)
      for (j=0; j<3; j++)
        g_pt[i][j]=((1.-cpm[61])*g_inpts[i][j]+cpm[61]*g_interp[i][j]);
	}
}
*/



 /* squash and stretch of head (except neck)*/
void sub57(int off)

{
   int i;
   if (cpm[57]!=ipm[57]) {
   if (cpm[57]==0.) cpm[57]=.0000001;
   	for (i=14+off; i<=293+off; i++) {
   	   g_pt[i][0]=g_pt[i][0]*cpm[57];
   	   g_pt[i][1]=g_pt[i][1]*(1./cpm[57]);
	}
	/* upper neck is half effect */
   	for (i=6+off; i<=13+off; i++) {
   	   g_pt[i][0]=g_pt[i][0]*((cpm[57]+1.)*.5);
   	   g_pt[i][1]=g_pt[i][1]*(1./((cpm[57]+1.)*.5));
	}
	i=294+off;
   	   g_pt[i][0]=g_pt[i][0]*((cpm[57]+1.)*.5);
   	   g_pt[i][1]=g_pt[i][1]*(1./((cpm[57]+1.)*.5));
	if (off) {
   	for (i=602; i<=624; i++) {
   	   g_pt[i][0]=g_pt[i][0]*cpm[57];
   	   g_pt[i][1]=g_pt[i][1]*(1./cpm[57]);
	}
#ifndef IRIS4Dnot
   	for (i=637; i<=g_np; i++) {
   	   g_pt[i][0]=g_pt[i][0]*cpm[57];
   	   g_pt[i][1]=g_pt[i][1]*(1./cpm[57]);
	}
#endif
	}
   }
}


   	/*	chin to mouth Y scaling		*/

void sub35(int off)
{
   int i;
   if (cpm[35]!=ipm[35]) {
   	for (i=6+off; i<=43+off; i++)
   		g_pt[i][1]=g_pt[45+off][1]+cpm[35]*(g_pt[i][1]-g_pt[45+off][1]);
   g_pt[294+off][1]=g_pt[45+off][1]+cpm[35]*(g_pt[294+off][1]-g_pt[45+off][1]);
   }
}


   	/*	chin to eye Y scaling		*/

void sub36(int off)
{
   int i;
   if (cpm[36]!=ipm[36]) {
   	for (i=6+off; i<=134+off; i++)
   		g_pt[i][1]=g_pt[128+off][1]+cpm[36]*(g_pt[i][1]-g_pt[128+off][1]);
	if (off)
   	for (i=1300; i<=1496; i++)	/* teeth */
   		g_pt[i][1]=g_pt[128][1]+cpm[36]*(g_pt[i][1]-g_pt[128][1]);
       g_pt[294+off][1]=g_pt[128+off][1]+cpm[36]*(g_pt[294+off][1]-g_pt[128+off][1]);

        g_pt[287+off][1]=g_pt[128+off][1]+cpm[36]*(g_pt[287+off][1]-g_pt[128+off][1]);
   }
}
   	/*  forehead buldge		*/

void sub25(int off)

{
   //int i,j;
   /*
   for (i=157+off; i<=171+off; i++)
      for (j=0; j<3; j++)
        g_pt[i][j]=((1.-cpm[25])*g_inpts[i][j]+cpm[25]*g_interp[i][j]);
	*/
}

void sub23(int off)

{
move23(33+off,37+off,.0,off);
move23(31+off,32+off,.5,off);
move23(23+off,26+off,1.0,off);
/*
move23(16+off,17+off,.8);
move23(14+off,15+off,.6); 
*/
}

void move23(int beg,int end,float tap,int off)
{
int i;
	if ((cpm[23]) > -.3)
   	   for (i=beg; i<=end; i++)
   	      g_pt[i][1]+=(cpm[23]*tap);
	  else {
	   if (tap < 1) tap=tap+.4;
   	   for (i=beg; i<=end; i++)
   	      if (off==0) g_pt[i][0]-=(((cpm[23]+.3)*tap)*4);
   	      else  g_pt[i][0]+=(((cpm[23]+.3)*tap)*4.);
	   if ((cpm[23]) > -.4)
   	       g_pt[i][1]-=(((cpm[23]+.4)*tap)*6.);
	  }

}

/*
 *****************  TOP OF HEAD  **********************************
*/

void hsub58(off)  /* lerp to sphere */

{
sub58a(116,118); sub58a(416,418);
sub58a(122,124); sub58a(422,424);
sub58a(135,137); sub58a(435,437);
sub58a(157,171); sub58a(457,471);
}


void sub58a(int beg,int end)  /* lerp to sphere */
{
int i,j;
float eps=0.0,lerp;
float lenall,len[3],
      eyer[3],  	/* eyer is radius of sphere in 3d */
      eyem[3];  	/* eyem is move of sphere in 3d */
lerp=cpm[58];
eyer[0]=.7;  /* cpm[63] */
eyer[1]=1.6; /* cpm[64] */
eyer[2]=.9;  /* cpm[65] */
eyem[0]=.04; /* cpm[66] */
eyem[1]= -.2; /* cpm[67] */
eyem[2]=.0;  /* cpm[68] */
/*	head mapping for a scaled sphere */
  eps = .002;

  for (i=beg ; i<=end; i++) {
        for (j=0; j<3; j++) {
           g_pt[i][j] -= eyem[j];
           len[j] = (g_pt[i][j]*g_pt[i][j]) / ((eyer[j]+eps)*(eyer[j]+eps));
	}
        lenall = 1 / (sqrt(len[0]+len[1]+len[2]));
        for (j=0; j<3; j++) {    /* map pts on sphere */
           g_pt[i][j] = (lerp*(lenall*g_pt[i][j])+(1.-lerp)*g_pt[i][j]);
           g_pt[i][j] += eyem[j];
	   }
      }
}

void sub58(int off)  /* scale top of head */

{
int i;

  if (cpm[58]!=ipm[58]) {
  for (i=0; i<=g_np; i++) {
	if ( g_pt[i][1] > cpm[59] ) {
           g_pt[i][1] -= cpm[59];
           g_pt[i][1] =  g_pt[i][1] * cpm[58];
           g_pt[i][1] += cpm[59];
      }
      else if ( g_pt[i][1] > ( cpm[59] -.04)  ) {
           g_pt[i][1] -= cpm[59];
           g_pt[i][1] =  g_pt[i][1] * (cpm[58] * 1.1);
           g_pt[i][1] += cpm[59];
      }
   }
   }
}

 /* skew top of head */
void sub37(int off)

{
   int i,j;
   float tmp;
double CTM[4][4],dpt[3];
  if (cpm[37]!=ipm[37]) {
  for (i=0; i<=g_np; i++) {
	if ( g_pt[i][1] > cpm[59] ) {
          for (j=0; j<3; j++)  dpt[j]=g_pt[i][j];
          l3d_ident(CTM);
          l3d_skew(CTM,RADIANS((float)cpmr[37]),2,1);
          l3d_xformd(CTM,dpt,dpt);
          for (j=0; j<3; j++)  g_pt[i][j]=dpt[j];
      }
      else if ( g_pt[i][1] > ( cpm[59] -.04)  ) {
          for (j=0; j<3; j++)  dpt[j]=g_pt[i][j];
          l3d_ident(CTM);
	  tmp=cpm[37]*.99;
          l3d_skew(CTM,RADIANS((float)tmp),2,1);
          l3d_xformd(CTM,dpt,dpt);
          for (j=0; j<3; j++)  g_pt[i][j]=dpt[j];
      }
    }
  }
}

/*
 *****************  SIDE OF HEAD  **********************************
*/

void sub40(int off)  /* scale side of head */

{
int i;
float     left,right,scf;  	/* eyem is move of sphere in 3d */
left= cpm[41];
right= cpm[42];
/*	head mapping for a scaled sphere */
if (cpm[40] != 0.0)
if (cpm[40] != ipm[40]) {
if (off==0) {
  for (i=0 ; i<=g_np; i++)
	if ( g_pt[i][0] > left ) {
           g_pt[i][0] -= left;
           g_pt[i][1] -= .2;
         scf = (g_pt[i][1]*1.2+(1.-g_pt[i][1])*cpm[40]);
           g_pt[i][0] =  g_pt[i][0] * scf;
           g_pt[i][0] += left;
           g_pt[i][1] += .2;
      }
 } else {
  for (i=0 ; i<=g_np; i++)
	if ( g_pt[i][0] < right ) {
           g_pt[i][0] -= right;
         scf = (g_pt[i][1]*1.2+(1.-g_pt[i][1])*cpm[40]);
           g_pt[i][0] =  g_pt[i][0] * scf;
           g_pt[i][0] += right;
      }
   }
 }
}

/*
 *****************  NECK  **********************************
*/

/* Neck y offset length */
void sub53(int off)

{
   int i;
  if (cpm[53]!=ipm[53]) {
   for (i=1+off; i<=5+off; i++) g_pt[i][1]=g_pt[i][1]+cpm[53];
   if (off) for (i=626; i<=651; i++) g_pt[i][1]=g_pt[i][1]+cpm[53];
   }
}

/* neck scale */
void sub33(int off)

{
int i;
   if (cpm[33]!=ipm[33]) {
   for (i=1+off; i<=5+off; i++) {
      g_pt[i][2]-=HEADOFF;
      g_pt[i][0]*=cpm[33]; g_pt[i][2]*=cpm[33];
      g_pt[i][2]+=HEADOFF;
      }
   for (i=6+off; i<=8+off; i++) {
      g_pt[i][2]-=HEADOFF;
      g_pt[i][0]*=cpm[33]*1.1; g_pt[i][2]*=cpm[33]*1.1;
      g_pt[i][2]+=HEADOFF;
      }
   i=9+off;
   g_pt[i][2]-=HEADOFF;
   g_pt[i][0]*=cpm[33]*1.; g_pt[i][2]*=cpm[33]*1.;
   g_pt[i][2]+=HEADOFF;
   i=10+off;
   g_pt[i][2]-=HEADOFF;
   g_pt[i][0]*=cpm[33]*.93; g_pt[i][2]*=cpm[33]*.93;
   g_pt[i][2]+=HEADOFF;
   i=294+off;
   g_pt[i][2]-=HEADOFF;
   g_pt[i][0]*=cpm[33]*.87; g_pt[i][2]*=cpm[33]*.87;
   g_pt[i][2]+=HEADOFF;

   if (off) {
      for (i=626; i<=636; i++) {
        g_pt[i][2]-=HEADOFF;
        g_pt[i][0]*=cpm[33]; g_pt[i][2]*=cpm[33];
        g_pt[i][2]+=HEADOFF;
        }
      for (i=637; i<=651; i++) {
        g_pt[i][2]-=HEADOFF;
        g_pt[i][0]=(g_pt[i][0]+g_pt[i][0])/2.6; g_pt[i][2]=(g_pt[i][2]+g_pt[i][2])/2.3;
        g_pt[i][2]+=HEADOFF;
        }
   }
   }
}

/* rot neck x */

void sub54(int off)

{
int i,j, off2=100;
double CTM[4][4],dpt[3];
float neckmid[3];


  if (cpm[54]!=ipm[54]) {
	neckmid[0]=0.0;
	neckmid[1]=g_pt[321][1];
	neckmid[2]=0.0;

l3d_ident(CTM);
l3d_rot(CTM,RADIANS((float)cpmr[54]),0);
   	for (i=14+off; i<=293+off; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}
	if (off) {
           for (i=602; i<=624; i++) {
             for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	   }
   	   for (i=637; i<=1500; i++) {
             for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
          }
	}

        if (off) off2=100; else off2=0;
   	for (i=1501+off2; i<=1570+off2; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}

	l3d_ident(CTM);
        l3d_rot(CTM,RADIANS((float)(cpm[54]*.5)),1);
   	for (i=6+off; i<=13+off; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}
    }
}


/* rot neck y */
void sub55(int off)

{
int i,j,off2=100;
double CTM[4][4],dpt[3];
float neckmid[3];

  if (cpm[55]!=ipm[55]) {
	neckmid[0]=0.0;
	neckmid[1]=g_pt[321][1];
	neckmid[2]=0.0;

l3d_ident(CTM);
l3d_rot(CTM,RADIANS((float)cpmr[55]),1);
   	for (i=14+off; i<=293+off; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}
	if (off) {
   	   for (i=602; i<=624; i++) {
             for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	   }
   	   for (i=637; i<=1500; i++) {
             for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
          }
	}

        if (off) off2=100; else off2=0;
   	for (i=1501+off2; i<=1570+off2; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}

	l3d_ident(CTM);
        l3d_rot(CTM,RADIANS((float)(cpm[55]*.5)),1);
   	for (i=6+off; i<=13+off; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}
    }
}

/* rot neck z  */

void sub56(int off)

{
int i,j,off2=100;
double CTM[4][4],dpt[3];
float neckmid[3];

  if (cpm[56]!=ipm[56]) {
	neckmid[0]=0.0;
	neckmid[1]=g_pt[321][1];
	neckmid[2]=0.0;

l3d_ident(CTM);
l3d_rot(CTM,RADIANS((float)cpmr[56]),2);
   	for (i=14+off; i<=293+off; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}
	if (off) {
   	   for (i=602; i<=624; i++) {
             for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	   }
   	   for (i=637; i<=1500; i++) {
             for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
          }
	}

        if (off) off2=100; else off2=0;
   	for (i=1501+off2; i<=1570+off2; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}

	l3d_ident(CTM);
        l3d_rot(CTM,RADIANS((float)(cpm[56]*.5)),1);
   	for (i=6+off; i<=13+off; i++) {
          for (j=0; j<3; j++) {  g_pt[i][j]-=neckmid[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]+=neckmid[j]; }
	}
    }
}

/*
 *****************  CHIN  **********************************

   	/*	move chin in Z		*/
void sub31(int off)

{
   int i;
  if (cpm[31]!=ipm[31]) {
   for (i=11+off; i<=40+off; i++) g_pt[i][2]=g_pt[i][2]+cpm[31];
   /* i=294+off; g_pt[i][2]=g_pt[i][2]+cpm[31]; */
   }
}

   	/*	move chin in Y		*/
void sub32(int off)

{
   int i;
  if (cpm[32]!=ipm[32]) {
   for (i=11+off; i<=40+off; i++) g_pt[i][1]=g_pt[i][1]+cpm[32];
   /* i=294+off; g_pt[i][1]=g_pt[i][1]+cpm[32]; */
    }
}

/*
********************  NOSE  ******************************
*/

   	/*	move end of nose in z	*/

void sub26(int off)

{
  if (cpm[26]!=ipm[26]) {
	movep(26,2, 74, 94, 1.,off);
	movep(26,2, 97, 101, 1.,off);
	movep(26,2, 71, 72, .5,off);
	movep(26,2, 95, 96, .5,off);
  }
}

   	/*	move end of nose in y	*/

void sub27(int off)

{
  if (cpm[27]!=ipm[27]) {
	movep(27,1, 74, 94, 1.,off);
	movep(27,1, 97, 101, 1.,off);
	movep(27,1, 71, 73, .5,off);
	movep(27,1, 95, 96, .5,off);
  }
}
   	/*	X scale end of nose		*/

void sub10(int off)

{
  if (cpm[10]!=ipm[10]) {
	scalep(10,0, 74, 94, 1.,off);
	scalep(10,0, 97, 101, 1.,off);
  }
}

   	/*	interp nostrils		*/

/*
void sub13(int off)

{
   int i,j;
  if (cpm[13]!=ipm[13]) {
   for (i=74+off; i<=101+off; i++)
      for (j=0; j<3; j++)
        g_pt[i][j]=((1.-cpm[13])*g_interp[i][j]+cpm[13]*g_inpts[i][j]);
  }
}
*/


   	/*	X scale bridge of nose		*/

void sub11(int off)

{

  if (cpm[11]!=ipm[11]) {
	scalep(11,0, 109, 111, 1.,off);
	scalep(11,0, 126, 128, 1.,off);
   	/*
	scalep(11,0, 130, 131, .5,off);
	scalep(11,0, 113, 113, .5,off);
	for (i=109+off; i<=113+off; i++)
   	for (i=126+off; i<=130+off; i++)
	*/
	}
}

/*
********************* CHEEK *********************************
*/
   	/*	cheek X scale		*/

void sub20(int off)

{
   int i;
  if (cpm[20]!=ipm[20]) {
   	for ( i=102+off; i<=107+off; i++ )
   		g_pt[i][0]=g_pt[i][0]*cpm[20];
   	for ( i=113+off; i<=118+off; i++ )
   		g_pt[i][0]=g_pt[i][0]*cpm[20];
   	for ( i=119+off; i<=124+off; i++ )
   		g_pt[i][0]=g_pt[i][0]*cpm[20];
   	for ( i=132+off; i<=137+off; i++ )
   		g_pt[i][0]=g_pt[i][0]*cpm[20];
  }
}


void movep(int tpm,int tpt,int beg,int end,float tap,int off) 
{
int i,j;
   if (off<=300) {
	if (tpt < 4 ) {
   	   for (i=beg; i<=end; i++)
   	      g_pt[i+off][tpt]+=(cpm[tpm]*tap);
	}
	else {
   	   for (i=beg; i<=end; i++)
   	      for (j=0; j<=2; j++)
   	          g_pt[i+off][j]+=(cpm[tpm]*tap);
	}
   }
}

void scalep(int tpm,int tpt,int beg,int end,float tap,int off) 
{
int i,j;
   if (off<=300) {
	if (tpt < 4 ) {
   	   for (i=beg; i<=end; i++)
   	      g_pt[i+off][tpt]*=(1+((cpm[tpm]-1)*tap));
	}
	else {
   	   for (i=beg; i<=end; i++)
   	      for (j=0; j<=2; j++)
   	          g_pt[i+off][j]*=(1+((cpm[tpm]-1)*tap));
	}
    }
}
