/* ========================================================================== MAKE_FACE_C ============================================================================= FUNCTION NAMES face_reset -- reset the face to neutral. create_face -- creates the face data create_face -- returns a pointer to the head datastructure. make_face -- makes a face from the two input files. add_polygon_to_face -- adds a polygon to the face data structure. reflect_polygon -- reflect a polygon in the Y axis. void averaged_vertex_normals - compute the average vertex normals. data_struct -- create the datastructure for the face. C SPECIFICATIONS void face_reset ( HEAD *face ) HEAD *create_face ( char *f1, char *f2 ) HEAD *create_face ( f1, f2 ) make_face ( HEAD *face ) add_polygon_to_face ( POLYGON *p, HEAD *face ) reflect_polygon ( POLYGON *poly, HEAD *face ) void averaged_vertex_normals ( HEAD *face, int p, float *n1, float *n2, float *n3 ) data_struct ( HEAD *face ) DESCRIPTION This module is where the face data structures are created. T his module comes as is with no warranties. HISTORY 16-Dec-94 Keith Waters (waters) at DEC's Cambridge Research Lab Created. Modified 22-Nov-96 Sing Bing Kang (sbk@crl.dec.com) Added function expressions() to enable changing facial expression ============================================================================ */ #include /* C header for any math functions */ #include /* C header for standard I/O */ #include /* For String compare */ #include #ifndef WIN32 #include #include #endif #include "memory.h" /* Local memory allocation macros */ #include "head.h" /* local header for the face */ void reflect_polygon ( POLYGON *poly, HEAD *face ); void add_polygon_to_face ( POLYGON *p, HEAD *face ); void make_face ( HEAD *face ); /* ========================================================================= */ /* face_reset */ /* ========================================================================= */ /* ** Resets the geometry of the face to neutral. ** */ void face_reset ( HEAD *face ) { int i,j,k ; for ( i=0; inpolygons; i++ ) { for ( j=0; j<3; j++ ) { for ( k=0; k<3; k++ ) { face->polygon[i]->vertex[j]->xyz[k] = face->polygon[i]->vertex[j]->nxyz[k] ; } } } } /* ========================================================================= expressions Written by: Sing Bing Kang Date: 11/22/96 ========================================================================= */ /* ** Produces the facial expressions as indicated by the muscle contraction ** vector ** */ void expressions ( HEAD *face, int e ) { int m; fprintf( stderr, "Expression: %s\n", face->expression[e]->name ); for (m=0; mnmuscles; m++) { float m_val = face->expression[e]->m[m], m_diff = m_val - face->muscle[m]->mstat; face->muscle[m]->mstat = m_val; activate_muscle ( face, face->muscle[m]->head, face->muscle[m]->tail, face->muscle[m]->fs, face->muscle[m]->fe, face->muscle[m]->zone, m_diff ) ; } } /* ========================================================================= */ /* create_face */ /* ========================================================================= */ /* ** create the default structures for the face and retrun a pointer. ** */ HEAD *create_face ( char *f1, char *f2 ) { HEAD *h ; h = _new ( HEAD ) ; h->npolygons = 0 ; h->npindices = 0 ; h->npolylinenodes = 0 ; read_polygon_indices ( f1, h ) ; read_polygon_line ( f2, h ) ; make_face ( h ) ; return ( h ) ; } /* ========================================================================= */ /* make_face */ /* ========================================================================= */ /* ** makes the face from the two input files. ** */ void make_face ( HEAD *face ) { POLYGON *p ; int i, ii, j, k, p1, p2, p3, p4 ; int parray[4] ; for ( i=0, ii=0; i < face->npindices; i++,ii+=4 ) { p1 = face->indexlist[ii] -1 ; p2 = face->indexlist[ii+1] -1 ; p3 = face->indexlist[ii+2] -1 ; p4 = face->indexlist[ii+3] -1 ; for (j=0; j<4; j++) parray[j] = face->indexlist[ii+j] -1; if ( p1 == 999 ) { p = _new ( POLYGON ) ; for (j=0; j<3; j++) { p->vertex[j] = _new ( VERTEX ) ; p->vertex[j]->np = 0 ; } for (j=0; j<3; j++) p->vertex[0]->nxyz[j] = p->vertex[0]->xyz[j] = face->polyline[ p2*3 + j ] ; for (j=0; j<3; j++) p->vertex[1]->nxyz[j] = p->vertex[1]->xyz[j] = face->polyline[ p3*3 + j ] ; for (j=0; j<3; j++) p->vertex[2]->nxyz[j] = p->vertex[2]->xyz[j] = face->polyline[ p4*3 + j ] ; add_polygon_to_face ( p, face ) ; reflect_polygon ( p, face ) ; } else { p = _new ( POLYGON ) ; for (j=0; j<3; j++) { p->vertex[j] = _new ( VERTEX ) ; p->vertex[j]->np = 0 ; } for (k=0; k<3; k++) { for (j=0; j<3; j++) p->vertex[k]->nxyz[j] = p->vertex[k]->xyz[j] = face->polyline[ parray[k]*3 + j ] ; } add_polygon_to_face ( p, face ) ; reflect_polygon ( p, face ) ; p = _new ( POLYGON ) ; for (j=0; j<3; j++) { p->vertex[j] = _new ( VERTEX ) ; p->vertex[j]->np = 0 ; } for (j=0; j<3; j++) p->vertex[0]->nxyz[j] = p->vertex[0]->xyz[j] = face->polyline[ p1*3 + j ] ; for (j=0; j<3; j++) p->vertex[1]->nxyz[j] = p->vertex[1]->xyz[j] = face->polyline[ p3*3 + j ] ; for (j=0; j<3; j++) p->vertex[2]->nxyz[j] = p->vertex[2]->xyz[j] = face->polyline[ p4*3 + j ] ; add_polygon_to_face ( p, face ) ; reflect_polygon ( p, face ) ; } } } /* ========================================================================= */ /* add_polygon_to_face */ /* ========================================================================= */ /* ** add a polygon to the face structure. ** */ void add_polygon_to_face ( POLYGON *p, HEAD *face ) { int nn ; if(face->npolygons == 0) face->polygon = _new_array(POLYGON *, 500) ; else if(face->npolygons % 500 == 0) face->polygon = _resize_array(face->polygon,POLYGON *,face->npolygons+500) ; nn = face->npolygons ; face->polygon[nn] = p ; face->npolygons++ ; } /* ========================================================================= */ /* reflect_polygon */ /* ========================================================================= */ /* ** Reflects all the polygons in the half-face and adds them to ** the data structure. ** */ void reflect_polygon ( POLYGON *poly, HEAD *face ) { POLYGON *newp ; float temp[3] ; int i, j ; /* * Allocate memory for the new polygon. */ newp = _new ( POLYGON ) ; for (j=0; j<3; j++) { newp->vertex[j] = _new ( VERTEX ) ; newp->vertex[j]->np = 0 ; } /* * Load the old polygon values. */ for (i=0; i<3; i++) for (j=0; j<3; j++) newp->vertex[i]->nxyz[j] = newp->vertex[i]->xyz[j] = poly->vertex[i]->xyz[j] ; /* * flip the X component. */ for (i=0; i<3; i++) newp->vertex[i]->nxyz[0] = newp->vertex[i]->xyz[0] = -newp->vertex[i]->xyz[0] ; /* * Re-order the vertices, flip 0 and 1. */ for (j=0; j<3; j++) temp[j] = newp->vertex[0]->xyz[j] ; for (j=0; j<3; j++) newp->vertex[0]->nxyz[j] = newp->vertex[0]->xyz[j] = newp->vertex[1]->xyz[j]; for (j=0; j<3; j++) newp->vertex[1]->nxyz[j] = newp->vertex[1]->xyz[j] = temp[j] ; add_polygon_to_face ( newp, face ) ; } /* ========================================================================= */ /* averaged_vertex_normals */ /* ========================================================================= */ /* ** Caculates the averaged polygon normal. */ void averaged_vertex_normals ( HEAD *face, int p, float *n1, float *n2, float *n3 ) { int i,j,np, pt ; float norm[3] ; for (i=0; i<3; i++) norm[i] = 0.0 ; np = face->polygon[p]->vertex[0]->np ; for ( i=0; ipolygon[p]->vertex[0]->plist[i] ; for ( j=0; j<3; j++) { norm[j] += face->polygon[pt]->vertex[0]->norm[j] ; } } for (i=0; i<3; i++) norm[i] = norm[i] / (float)np ; for (i=0; i<3; i++) n1[i] = norm[i] ; for (i=0; i<3; i++) norm[i] = 0.0 ; np = face->polygon[p]->vertex[1]->np ; for ( i=0; ipolygon[p]->vertex[1]->plist[i] ; for ( j=0; j<3; j++) { norm[j] += face->polygon[pt]->vertex[1]->norm[j] ; } } for (i=0; i<3; i++) norm[i] = norm[i] / (float) np ; for (i=0; i<3; i++) n2[i] = norm[i] ; for (i=0; i<3; i++) norm[i] = 0.0 ; np = face->polygon[p]->vertex[2]->np ; for ( i=0; ipolygon[p]->vertex[2]->plist[i] ; for ( j=0; j<3; j++) { norm[j] += face->polygon[pt]->vertex[2]->norm[j] ; } } for (i=0; i<3; i++) norm[i] = norm[i]/ (float) np ; for (i=0; i<3; i++) n3[i] = norm[i] ; } /* ========================================================================= */ /* data_struct */ /* ========================================================================= */ /* ** Create a new data structure for the polygons. ** */ #define DATA_STRUCT_DEBUG 0 void data_struct ( HEAD *face ) { int i,j, n ; int flag, cptr ; float x1,y1,z1, x2, y2, z2, x3, y3, z3 ; float tx1, ty1, tz1, tx2, ty2, tz2, tx3, ty3, tz3 ; for (i=0; inpolygons; i++ ){ x1 = face->polygon[i]->vertex[0]->xyz[0] ; y1 = face->polygon[i]->vertex[0]->xyz[1] ; z1 = face->polygon[i]->vertex[0]->xyz[2] ; x2 = face->polygon[i]->vertex[1]->xyz[0] ; y2 = face->polygon[i]->vertex[1]->xyz[1] ; z2 = face->polygon[i]->vertex[1]->xyz[2] ; x3 = face->polygon[i]->vertex[2]->xyz[0] ; y3 = face->polygon[i]->vertex[2]->xyz[1] ; z3 = face->polygon[i]->vertex[2]->xyz[2] ; #if DATA_STRUCT_DEBUG fprintf (stderr,"BASE polygon: %d\n", i) ; fprintf (stderr,"x1: %f y1: %f z1: %f\n", x1,y1,z1) ; fprintf (stderr,"x1: %f y1: %f z1: %f\n", x2,y2,z2) ; fprintf (stderr,"x1: %f y1: %f z1: %f\n", x3,y3,z3) ; #endif j = 0 ; flag = 0 ; while ( !flag && jnpolygons ) { tx1 = face->polygon[j]->vertex[0]->xyz[0] ; ty1 = face->polygon[j]->vertex[0]->xyz[1] ; tz1 = face->polygon[j]->vertex[0]->xyz[2] ; tx2 = face->polygon[j]->vertex[1]->xyz[0] ; ty2 = face->polygon[j]->vertex[1]->xyz[1] ; tz2 = face->polygon[j]->vertex[1]->xyz[2] ; tx3 = face->polygon[j]->vertex[2]->xyz[0] ; ty3 = face->polygon[j]->vertex[2]->xyz[1] ; tz3 = face->polygon[j]->vertex[2]->xyz[2] ; #if DATA_STRUCT_DEBUG fprintf (stderr, "COMPARED TO polygon: %d\n", j) ; fprintf (stderr,"tx1: %f ty1: %f tz1: %f\n", tx1,ty1,tz1) ; fprintf (stderr,"tx1: %f ty1: %f tz1: %f\n", tx2,ty2,tz2) ; fprintf (stderr,"tx1: %f ty1: %f tz1: %f\n", tx3,ty3,tz3) ; #endif if ( x1 == tx1 && y1 == ty1 && z1 == tz1 || x1 == tx2 && y1 == ty2 && z1 == tz2 || x1 == tx3 && y1 == ty3 && z1 == tz3) { cptr = j ; #if DATA_STRUCT_DEBUG fprintf (stderr,"found a vertex match on polygon: %d and %d\n", i,j); #endif n = face->polygon[i]->vertex[0]->np ; face->polygon[i]->vertex[0]->plist[n] = cptr ; face->polygon[i]->vertex[0]->np++ ; #if DATA_STRUCT_DEBUG fprintf (stderr,"loaded: %d onto polygon: %d vertex[0]\n", cptr, i) ; fprintf (stderr,"total on vertex: %d\n", face->polygon[i]->vertex[0]->np); #endif } j++ ; } /* end while */ j = 0 ; flag = 0 ; while ( !flag && jnpolygons ) { tx1 = face->polygon[j]->vertex[0]->xyz[0] ; ty1 = face->polygon[j]->vertex[0]->xyz[1] ; tz1 = face->polygon[j]->vertex[0]->xyz[2] ; tx2 = face->polygon[j]->vertex[1]->xyz[0] ; ty2 = face->polygon[j]->vertex[1]->xyz[1] ; tz2 = face->polygon[j]->vertex[1]->xyz[2] ; tx3 = face->polygon[j]->vertex[2]->xyz[0] ; ty3 = face->polygon[j]->vertex[2]->xyz[1] ; tz3 = face->polygon[j]->vertex[2]->xyz[2] ; if ( x2 == tx1 && y2 == ty1 && z2 == tz1 || x2 == tx2 && y2 == ty2 && z2 == tz2 || x2 == tx3 && y2 == ty3 && z2 == tz3) { cptr = j ; n = face->polygon[i]->vertex[1]->np ; face->polygon[i]->vertex[1]->plist[n] = j ; face->polygon[i]->vertex[1]->np++ ; } j++ ; } /* end while */ j = 0 ; flag = 0 ; while ( !flag && jnpolygons ) { tx1 = face->polygon[j]->vertex[0]->xyz[0] ; ty1 = face->polygon[j]->vertex[0]->xyz[1] ; tz1 = face->polygon[j]->vertex[0]->xyz[2] ; tx2 = face->polygon[j]->vertex[1]->xyz[0] ; ty2 = face->polygon[j]->vertex[1]->xyz[1] ; tz2 = face->polygon[j]->vertex[1]->xyz[2] ; tx3 = face->polygon[j]->vertex[2]->xyz[0] ; ty3 = face->polygon[j]->vertex[2]->xyz[1] ; tz3 = face->polygon[j]->vertex[2]->xyz[2] ; if ( x3 == tx1 && y3 == ty1 && z3 == tz1 || x3 == tx2 && y3 == ty2 && z3 == tz2 || x3 == tx3 && y3 == ty3 && z3 == tz3) { cptr = j ; n = face->polygon[i]->vertex[2]->np ; face->polygon[i]->vertex[2]->plist[n] = cptr ; face->polygon[i]->vertex[2]->np++ ; } j++ ; } /* end while */ } /* end for i */ }