// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 // make a subdiv surface static int S2totalverts = 0; //OVOX *OVX; static void avg_pnts( int a, int b, VERT * p, SVMAP * sv ); static void calc_dominance( void ); static void init_subdiv( void ) { int x, y, z; for( x = 0; x < OVLIMIT; x++ ) for( y = 0; y < OVLIMIT; y++ ) for( z = 0; z < OVLIMIT; z++ ) { OVX[x][y][z].totalp = 0; } } static void build_pairs( void ) { int x, y, z; for( x = 0; x < Stotalverts; x++ ) Stag[x] = 0; Stotaledges = 0; for( x = 0; x < Stotalfaces; x++ ) if( Sface_end[x] - Sface_start[x] > 0 ) { for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int y1; int g, g1; y1 = y + 1; if( y1 == Sface_end[x] ) y1 = 0; g = Sfacelist[y]; g1 = Sfacelist[y1]; if( Sedgeflag[g] && Sedgeflag[g1] ) if( ( Stag[g] + Stag[g1] ) != 2 ) { Stag[g] = 1; Stag[g1] = 1; Stotaledges++; } } } if( Sedgepairs != NULL ) Nfree( Sedgepairs ); Sedgepairs = NULL; if( Stotaledges > 0 ) Sedgepairs = ( int * ) malloc( Stotaledges * 2 * sizeof( int ) + 2 * sizeof( int ) ); for( x = 0; x < Stotalverts; x++ ) Stag[x] = 0; Stotaledges = 0; for( x = 0; x < Stotalfaces; x++ ) if( Sface_end[x] - Sface_start[x] > 0 ) { for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int y1; int g, g1; y1 = y + 1; if( y1 == Sface_end[x] ) y1 = 0; g = Sfacelist[y]; g1 = Sfacelist[y1]; if( Sedgeflag[g] && Sedgeflag[g1] ) if( ( Stag[g] + Stag[g1] ) != 2 ) { Stag[g] = 1; Stag[g1] = 1; Sedgepairs[Stotaledges * 2] = g; Sedgepairs[Stotaledges * 2 + 1] = g1; Stotaledges++; } } } } static void cleanup3( void ) { int x, y, z; int ix, iy, iz; VERT b1, b2, bnd; for( x = 0; x < OVLIMIT; x++ ) for( y = 0; y < OVLIMIT; y++ ) for( z = 0; z < OVLIMIT; z++ ) { if( OVX[x][y][z].totalp > 0 ) Nfree( OVX[x][y][z].plist ); OVX[x][y][z].totalp = 0; } b1.x = 10000.0f; b1.y = 10000.0f; b1.z = 10000.0f; b2.x = -100000.0f; b2.y = -100000.0f; b2.z = -100000.0f; for( x = 0; x < Stotalverts; x++ ) Stag[x] = 0; for( x = 0; x < Stotalfaces; x++ ) { if( ( Sface_end[x] - Sface_start[x] ) > 2 ) for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int g; g = Sfacelist[y]; Stag[g] = 1; } } for( x = 0; x < Stotalverts; x++ ) { if( Stag[x] ) { if( VS[x].x < b1.x ) b1.x = VS[x].x; if( VS[x].y < b1.y ) b1.y = VS[x].y; if( VS[x].z < b1.z ) b1.z = VS[x].z; if( VS[x].x > b2.x ) b2.x = VS[x].x; if( VS[x].y > b2.y ) b2.y = VS[x].y; if( VS[x].z > b2.z ) b2.z = VS[x].z; } } bnd.x = b2.x - b1.x; bnd.y = b2.y - b1.y; bnd.z = b2.z - b1.z; for( x = 0; x < Stotalfverts; x++ ) { int g; g = Sfacelist[x]; if( Stag[g] ) { ix = ( int ) ( ( ( VS[g].x - b1.x ) / ( bnd.x ) ) * ( float ) ( OVLIMIT - 1 ) ); iy = ( int ) ( ( ( VS[g].y - b1.y ) / ( bnd.y ) ) * ( float ) ( OVLIMIT - 1 ) ); iz = ( int ) ( ( ( VS[g].z - b1.z ) / ( bnd.z ) ) * ( float ) ( OVLIMIT - 1 ) ); // OVX[ix][iy][iz].plist[OVX[ix][iy][iz].totalp]=x; OVX[ix][iy][iz].totalp++; } } for( x = 0; x < OVLIMIT; x++ ) for( y = 0; y < OVLIMIT; y++ ) for( z = 0; z < OVLIMIT; z++ ) { if( OVX[x][y][z].totalp > 0 ) OVX[x][y][z].plist = ( int * ) malloc( OVX[x][y][z].totalp * sizeof( int ) ); OVX[x][y][z].totalp = 0; } for( x = 0; x < Stotalfverts; x++ ) { int g; g = Sfacelist[x]; if( Stag[g] ) { ix = ( int ) ( ( ( VS[g].x - b1.x ) / ( bnd.x ) ) * ( float ) ( OVLIMIT - 1 ) ); iy = ( int ) ( ( ( VS[g].y - b1.y ) / ( bnd.y ) ) * ( float ) ( OVLIMIT - 1 ) ); iz = ( int ) ( ( ( VS[g].z - b1.z ) / ( bnd.z ) ) * ( float ) ( OVLIMIT - 1 ) ); OVX[ix][iy][iz].plist[OVX[ix][iy][iz].totalp] = x; OVX[ix][iy][iz].totalp++; } } for( x = 0; x < OVLIMIT; x++ ) for( y = 0; y < OVLIMIT; y++ ) for( z = 0; z < OVLIMIT; z++ ) { int xx, yy; int g, g1; int q, q1; for( xx = 0; xx < OVX[x][y][z].totalp; xx++ ) { q = OVX[x][y][z].plist[xx]; if( q >= 0 ) { g = Sfacelist[q]; if( Skeepme[g] ) if( Stag[g] ) { // check all the others for( yy = 0; yy < OVX[x][y][z].totalp; yy++ ) { q1 = OVX[x][y][z].plist[yy]; if( q1 >= 0 ) { VERT cent; g1 = Sfacelist[q1]; if( VS[g1].x == VS[g].x ) if( VS[g1].y == VS[g].y ) if( VS[g1].z == VS[g].z ) { // SVMAP sv; // sv.totalp=0; // sv.plist=NULL; // avg_pnts(g1,g, ¢,&sv); // if (Svert2DfaceID[g].plist!=NULL) // free (Svert2DfaceID[g].plist); // Svert2DfaceID[g].plist=NULL; // Svert2DfaceID[g].totalp=0; // if (sv.totalp>0) // { // int xx; // Svert2DfaceID[g].plist= (BARY *) malloc (sv.totalp*sizeof(BARY)); // for (xx=0;xx 0 ) Nfree( OVX[x][y][z].plist ); OVX[x][y][z].plist = NULL; OVX[x][y][z].totalp = 0; } if( Svert2DfaceID != NULL ) for( x = 0; x < S2totalverts; x++ ) { if( Svert2DfaceID[x].plist != NULL ) { Nfree( Svert2DfaceID[x].plist ); Svert2DfaceID[x].plist = NULL; } } if( Svert2DfaceID != NULL ) free( Svert2DfaceID ); Svert2DfaceID = NULL; if( Svn != NULL ) free( Svn ); Svn=NULL; if( VS != NULL ) free( VS ); VS=NULL; if( SVtmp != NULL ) Nfree( SVtmp ); if( Sfacelist != NULL ) Nfree( Sfacelist ); if( Sface_start != NULL ) Nfree( Sface_start ); if( Sface_end != NULL ) Nfree( Sface_end ); if( Sedgeflag != NULL ) Nfree( Sedgeflag ); if( Stag != NULL ) Nfree( Stag ); if( Skeepme != NULL ) Nfree( Skeepme ); if( Sedgepairs != NULL ) Nfree( Sedgepairs ); Sedgepairs = NULL; Svn = NULL; VS = NULL; SVtmp = NULL; Sfacelist = NULL; Sface_start = NULL; Sface_end = NULL; Sedgeflag = NULL; Stag = NULL; Skeepme = NULL; VS = NULL; } Stotalverts = 0; Stotalverts = 0; S2totalverts = 0; Stotalfverts = 0; Stotaledges = 0; } //#endif static void Salloc( int divs ) { int tv, tf, tfv; int x; tv = Dtotalverts; tf = DUTtotalfaces; tfv = DUTtotalfverts; for( x = 0; x < divs; x++ ) { tv += tv * 8; tf += tf * 6; tfv += tfv * 6; } //free_subdivs(); // if (Stotalfaces>0) SNfree( ); S2totalverts = tv; Svn = ( VERT * ) malloc( tv * sizeof( VERT ) ); VS = ( VERT * ) malloc( tv * sizeof( VERT ) ); Sedgeflag = ( int * ) malloc( tv * sizeof( int ) ); //VSB=(VERT *) malloc (tfv*sizeof(VERT)); SVtmp = ( VERT * ) malloc( tv * sizeof( VERT ) ); Sfacelist = ( int * ) malloc( tfv * sizeof( int ) ); Sface_start = ( int * ) malloc( tf * sizeof( int ) ); Sface_end = ( int * ) malloc( tf * sizeof( int ) ); Stag = ( int * ) malloc( tv * sizeof( int ) ); Skeepme = ( int * ) malloc( tv * sizeof( int ) ); Svert2DfaceID = ( SVMAP * ) malloc( 2 * tv * sizeof( SVMAP ) ); for( x = 0; x < tv; x++ ) { Svert2DfaceID[x].totalp = 0; Svert2DfaceID[x].plist = NULL; } Stotalverts = 0; Stotalfaces = 0; Stotalfverts = 0; } static void Smake_normals( void ) { int x, f, q; q = 0; for( x = 0; x < Stotalverts; x++ ) { Svn[x].x = 0.0f; Svn[x].y = 0.0f; Svn[x].z = 0.0f; } for( f = 0; f < Stotalfaces; f++ ) { if( ( Sface_end[f] - Sface_start[f] ) > 0 ) { VERT v1, v2, v3; VERT uu, vv, cross; int x; x = Sface_start[f]; v1.x = VS[Sfacelist[x + 2]].x; v1.y = VS[Sfacelist[x + 2]].y; v1.z = VS[Sfacelist[x + 2]].z; v2.x = VS[Sfacelist[x + 1]].x; v2.y = VS[Sfacelist[x + 1]].y; v2.z = VS[Sfacelist[x + 1]].z; v3.x = VS[Sfacelist[x + 0]].x; v3.y = VS[Sfacelist[x + 0]].y; v3.z = VS[Sfacelist[x + 0]].z; v1.x -= v2.x; v1.y -= v2.y; v1.z -= v2.z; v3.x -= v2.x; v3.y -= v2.y; v3.z -= v2.z; uu.x = v1.x; uu.y = v1.y; uu.z = v1.z; vv.x = v3.x; vv.y = v3.y; vv.z = v3.z; uu = Vnorm( uu ); vv = Vnorm( vv ); cross = coord_cross( uu, vv ); v1.x = cross.x; v1.y = cross.y; v1.z = cross.z; v1 = Vnorm( v1 ); for( x = Sface_start[f]; x < Sface_end[f]; x++ ) { Svn[Sfacelist[x]].x += v1.x; Svn[Sfacelist[x]].y += v1.y; Svn[Sfacelist[x]].z += v1.z; } } } for( x = 0; x < Stotalverts; x++ ) { float a, b, c, d; a = Svn[x].x; b = Svn[x].y; c = Svn[x].z; d = sqrt( a * a + b * b + c * c ); if( d != 0.0 ) { a = a / d; b = b / d; c = c / d; } Svn[x].x = a; Svn[x].y = b; Svn[x].z = c; //#ifdef wavefront // vn[x].x = -vn[x].x; // vn[x].y = -vn[x].y; // vn[x].z = -vn[x].z; //#endif } } static void add_vert( VERT q, SVMAP * b ) { VS[Stotalverts] = q; // if (Svert2DfaceID[Stotalverts].totalp>0) if( Svert2DfaceID[Stotalverts].plist != NULL ) { Nfree( Svert2DfaceID[Stotalverts].plist ); Svert2DfaceID[Stotalverts].plist = NULL; Svert2DfaceID[Stotalverts].totalp = 0; } // Nfree(Svert2DfaceID[Stotalverts].plist); if( b->plist != NULL ) { int yy; if( b->totalp > 0 ) { Svert2DfaceID[Stotalverts].plist = ( BARY * ) malloc( b->totalp * sizeof( BARY ) ); Svert2DfaceID[Stotalverts].totalp = b->totalp; for( yy = 0; yy < b->totalp; yy++ ) { Svert2DfaceID[Stotalverts].plist[yy] = b->plist[yy]; } } } Skeepme[Stotalverts] = 1; Stotalverts++; // VSB[Stotalfverts]=b; } static void add_quad( int a, int b, int c, int d ) { Sfacelist[Stotalfverts] = a; Sfacelist[Stotalfverts + 1] = b; Sfacelist[Stotalfverts + 2] = c; Sfacelist[Stotalfverts + 3] = d; Sface_start[Stotalfaces] = Stotalfverts; Stotalfverts += 4; Sface_end[Stotalfaces] = Stotalfverts; Stotalfaces++; } static void avg_pnts( int a, int b, VERT * p, SVMAP * sv ) { SVMAP *asv, *bsv; int matchcount = 0; // don't assume there's a match for each one int x, y; asv = &Svert2DfaceID[a]; bsv = &Svert2DfaceID[b]; if( asv != NULL ) if( bsv != NULL ) //if ((asv->plist!=NULL)&&(bsv->plist!=NULL)) for( x = 0; x < asv->totalp; x++ ) for( y = 0; y < bsv->totalp; y++ ) { if( ( asv->plist != NULL ) && ( bsv->plist != NULL ) ) if( asv->plist[x].Dface == bsv->plist[y].Dface ) matchcount++; } // check both directions //if ((asv->plist!=NULL)&&(bsv->plist!=NULL)) //for (y=0;ytotalp;y++) //for (x=0;xtotalp;x++) // { // if (asv->plist[x].Dface==bsv->plist[y].Dface) matchcount++; // } if( sv->plist != NULL ) { Nfree( sv->plist ); sv->plist = NULL; } sv->totalp = matchcount; if( matchcount > 0 ) sv->plist = ( BARY * ) malloc( matchcount * sizeof( BARY ) ); matchcount = 0; if( asv != NULL ) if( bsv != NULL ) for( x = 0; x < asv->totalp; x++ ) for( y = 0; y < bsv->totalp; y++ ) { if( ( asv->plist != NULL ) && ( bsv->plist != NULL ) ) if( asv->plist[x].Dface == bsv->plist[y].Dface ) { sv->plist[matchcount].Dface = asv->plist[x].Dface; sv->plist[matchcount].bary.x = ( asv->plist[x].bary.x + bsv->plist[y].bary.x ) / 2.0f; sv->plist[matchcount].bary.y = ( asv->plist[x].bary.y + bsv->plist[y].bary.y ) / 2.0f; sv->plist[matchcount].bary.z = ( asv->plist[x].bary.z + bsv->plist[y].bary.z ) / 2.0f; matchcount++; } } // check both directions //if (asv!=NULL) //if (bsv!=NULL) //for (y=0;ytotalp;y++) //for (x=0;xtotalp;x++) // { //if ((asv->plist!=NULL)&&(bsv->plist!=NULL)) // if (asv->plist[x].Dface==bsv->plist[y].Dface) // { // sv->plist[matchcount].Dface=asv->plist[x].Dface; /// sv->plist[matchcount].bary.x= // (asv->plist[x].bary.x+bsv->plist[y].bary.x)/2.0f; // sv->plist[matchcount].bary.y= // (asv->plist[x].bary.y+bsv->plist[y].bary.y)/2.0f; // sv->plist[matchcount].bary.z= // (asv->plist[x].bary.z+bsv->plist[y].bary.z)/2.0f; // matchcount++; // } // } if( matchcount == 0 ) matchcount = 0; p->x = ( VS[a].x + VS[b].x ) / 2.0f; p->y = ( VS[a].y + VS[b].y ) / 2.0f; p->z = ( VS[a].z + VS[b].z ) / 2.0f; } static void cleanup( void ) { int x, y, z; for( x = 0; x < Stotalfverts; x++ ) { if( Stag[Sfacelist[x]] == 1 ) { VERT a; a = VS[Sfacelist[x]]; for( y = x + 1; y < Stotalfverts; y++ ) { VERT b; if( Stag[Sfacelist[y]] == 1 ) if( y != x ) { int aa1, bb1, cc1; int aa2, bb2, cc2; b = VS[Sfacelist[y]]; aa1 = ( int ) floor( a.x * 1000 ); bb1 = ( int ) floor( a.y * 1000 ); cc1 = ( int ) floor( a.z * 1000 ); aa2 = ( int ) floor( b.x * 1000 ); bb2 = ( int ) floor( b.y * 1000 ); cc2 = ( int ) floor( b.z * 1000 ); if( aa1 == aa2 ) if( bb1 == bb2 ) if( cc1 == cc2 ) { // Stag[Sfacelist[y]]=0; Sfacelist[y] = Sfacelist[x]; } } } } } } static void cleanup2( void ) { int x, y, z; for( x = 0; x < Stotalfverts; x++ ) { if( Stag[Sfacelist[x]] == 1 ) { VERT a; a = VS[Sfacelist[x]]; for( y = x + 1; y < Stotalfverts; y++ ) { VERT b; if( Stag[Sfacelist[y]] == 1 ) if( y != x ) { b = VS[Sfacelist[y]]; if( b.x == a.x ) if( b.y == a.y ) if( b.z == a.z ) { Stag[Sfacelist[y]] = 0; Sfacelist[y] = Sfacelist[x]; } } } } } for( x = 0; x < Stotalfaces; x++ ) { if( Skeepme[x] == 0 ) { Sface_start[x] = 0; Sface_end[x] = 0; } } } void smoothit( void ) { int x, y; int *edgetag = NULL; if( Stotalverts > 0 ) { edgetag = ( int * ) malloc( Stotalverts * sizeof( int ) ); for( x = 0; x < Stotalverts; x++ ) { Stag[x] = 0; SVtmp[x].x = 0; SVtmp[x].y = 0; SVtmp[x].z = 0; // SVtmp[x]=VS[x]; } for( x = 0; x < Stotalverts; x++ ) { SVtmp[x].x = 0; SVtmp[x].y = 0; SVtmp[x].z = 0; } for( x = 0; x < Stotalfaces; x++ ) if( ( Sface_end[x] - Sface_start[x] ) > 2 ) if( ( Sface_end[x] - Sface_start[x] == 4 ) || ( Sface_end[x] - Sface_start[x] == 3 ) ) { VERT cv; // SVMAP cb; int fvr = 0; // cb.totalp=0; // cb.plist=NULL; cv.x = ( VS[Sfacelist[Sface_start[x]]].x + VS[Sfacelist[Sface_start[x] + 2]].x ) / 2.0f; cv.y = ( VS[Sfacelist[Sface_start[x]]].y + VS[Sfacelist[Sface_start[x] + 2]].y ) / 2.0f; cv.z = ( VS[Sfacelist[Sface_start[x]]].z + VS[Sfacelist[Sface_start[x] + 2]].z ) / 2.0f; // avg_pnts(Sfacelist[Sface_start[x]],Sfacelist[Sface_start[x]+2], &cv,&cb); // find_center(x,&cv,&cb); fvr = Sface_end[x] - Sface_start[x]; if( ( fvr == 3 ) || ( fvr == 4 ) ) for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int g; g = Sfacelist[y]; SVtmp[g].x += cv.x; SVtmp[g].y += cv.y; SVtmp[g].z += cv.z; Stag[g]++; } // if (cb.plist!=NULL) // Nfree(cb.plist); // cb.plist=NULL; } for( x = 0; x < Stotalfaces; x++ ) if( ( Sface_end[x] - Sface_start[x] == 4 ) || ( Sface_end[x] - Sface_start[x] == 3 ) ) if( ( Sface_end[x] - Sface_start[x] ) > 0 ) { int gg; gg = Sface_end[x] - Sface_start[x]; if( ( gg != 3 ) && ( gg != 4 ) ) for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int g; g = Sfacelist[y]; Stag[g] = 0; } } for( x = 0; x < Stotalverts; x++ ) { edgetag[x] = 0; if( Skeepme[x] == 1 ) if( Stag[x] > 2 ) { VERT q; q = SVtmp[x]; VS[x].x = q.x / ( float ) ( Stag[x] ); VS[x].y = q.y / ( float ) ( Stag[x] ); VS[x].z = q.z / ( float ) ( Stag[x] ); } else if( Stag[x] != 0 ) edgetag[x] = 1; } // now do the edges for( x = 0; x < Stotalverts; x++ ) { Stag[x] = 0; SVtmp[x].x = 0; SVtmp[x].y = 0; SVtmp[x].z = 0; } for( x = 0; x < Stotalfaces; x++ ) if( ( Sface_end[x] - Sface_start[x] ) > 0 ) { int qq = 0, tq = 0; VERT cv, cb; cv.x = 0; cv.y = 0; cv.z = 0; for( qq = Sface_start[x]; qq < Sface_end[x]; qq++ ) { int g; g = Sfacelist[qq]; if( edgetag[g] ) { cv.x += VS[g].x; cv.y += VS[g].y; cv.z += VS[g].z; tq++; } } if( tq > 0 ) { cv.x /= ( float ) tq; cv.y /= ( float ) tq; cv.z /= ( float ) tq; } for( y = Sface_start[x]; y < Sface_end[x]; y++ ) if( edgetag[Sfacelist[y]] ) { int g; g = Sfacelist[y]; SVtmp[g].x += cv.x; SVtmp[g].y += cv.y; SVtmp[g].z += cv.z; Stag[g]++; } } for( x = 0; x < Stotalverts; x++ ) { if( Skeepme[x] == 1 ) if( Stag[x] > 0 ) { VERT q; q = SVtmp[x]; VS[x].x = q.x / ( float ) ( Stag[x] ); VS[x].y = q.y / ( float ) ( Stag[x] ); VS[x].z = q.z / ( float ) ( Stag[x] ); } } if( edgetag != NULL ) Nfree( edgetag ); edgetag = NULL; } } void loadfaces( void ) { int q; int x, y, z; int tf = 0; Stotalfaces = 0; Stotalverts = 0; Stotalfverts = 0; for( y = 0; y < DUTtotalfverts; y++ ) Sfacelist[y] = DUTfacelist[y]; for( y = 0; y < DUTtotalfaces; y++ ) { int fe; { Sface_start[y] = DUTface_start[y]; Sface_end[y] = DUTface_end[y]; fe = DUTface_end[y] - DUTface_start[y]; for( x = Sface_start[y]; x < Sface_end[y]; x++ ) { int g; g = Sfacelist[x]; Skeepme[g] = 1; //don't merge these points } } } for( y = 0; y < DUTtotalfaces; y++ ) { int fe; { fe = DUTface_end[y] - DUTface_start[y]; for( x = Sface_start[y]; x < Sface_end[y]; x++ ) if( DUTmtlgroup[y] >= 0 ) if( !( ( DUTmtlgroup[y] == splines ) && ( splines >= 0 ) ) ) { int g; g = Sfacelist[x]; if( !( ( fe == 3 ) || ( fe == 4 ) ) ) Skeepme[g] = 0; } } } Stotalfaces = DUTtotalfaces; Stotalfverts = DUTtotalfverts; for( y = 0; y < Dtotalverts; y++ ) { VS[y] = Dv[y]; Svn[y] = Dvn[y]; Sedgeflag[y] = 1; Stag[y] = 0; } Stotalverts = Dtotalverts; for( x = 0; x < S2totalverts; x++ ) { if( Svert2DfaceID[x].plist != NULL ) Nfree( Svert2DfaceID[x].plist ); Svert2DfaceID[x].plist = NULL; // Nfree(Svert2DfaceID[x].plist); Svert2DfaceID[x].totalp = 0; } for( x = 0; x < Stotalfaces; x++ ) { if( Sface_end[x] - Sface_start[x] >= 3 ) if( !( ( DUTmtlgroup[x] == splines ) && ( splines >= 0 ) ) ) { for( y = Sface_start[x] + 1; y < Sface_end[x] - 1; y++ ) { int g, g1, y1; y1 = y + 1; //if (y1==Sface_end[x]) y1=0; g = Sfacelist[y]; g1 = Sfacelist[y1]; Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp++; Svert2DfaceID[g].totalp++; Svert2DfaceID[g1].totalp++; } Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp++; Svert2DfaceID[Sfacelist[Sface_end[x] - 1]].totalp++; Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp++; } if( 0 == 1 ) if( ( ( DUTmtlgroup[x] == splines ) && ( splines >= 0 ) ) ) { int g; for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { g = Sfacelist[y]; Svert2DfaceID[g].totalp++; } tf++; } } for( x = 0; x < Stotalverts; x++ ) { if( Svert2DfaceID[x].plist != NULL ) { Nfree( Svert2DfaceID[x].plist ); Svert2DfaceID[x].plist = NULL; } Svert2DfaceID[x].plist = ( BARY * ) malloc( ( Svert2DfaceID[x].totalp + 1 ) * sizeof( BARY ) ); Svert2DfaceID[x].totalp = 0; } tf = 0; for( x = 0; x < Stotalfaces; x++ ) { if( !( ( DUTmtlgroup[x] == splines ) && ( splines >= 0 ) ) ) if( Sface_end[x] - Sface_start[x] >= 3 ) { for( y = Sface_start[x] + 1; y < Sface_end[x] - 1; y++ ) if( !( ( DUTmtlgroup[x] == splines ) && ( splines >= 0 ) ) ) { int g, g1, y1; y1 = y + 1; //if (y1==Sface_end[x]) y1=0; g = Sfacelist[y]; g1 = Sfacelist[y1]; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].Dface = tf; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].bary.x = 0.0f; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].bary.y = 0.0f; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].bary.z = 1.0f; Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp++; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].Dface = tf; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].bary.x = 0.0f; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].bary.y = 1.0f; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].bary.z = 0.0f; Svert2DfaceID[g].totalp++; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].Dface = tf; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].bary.x = 1.0f; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].bary.y = 0.0f; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].bary.z = 0.0f; Svert2DfaceID[g1].totalp++; tf++; } // close the poly if( !( ( DUTmtlgroup[x] == splines ) && ( splines >= 0 ) ) ) if( Sface_end[x] - Sface_start[x] >= 3 ) { int g, g1, y1; y = Sface_end[x] - 1; y1 = Sface_start[x]; g = Sfacelist[y]; g1 = Sfacelist[y1]; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].Dface = tf - 1; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].bary.x = 0.0f; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].bary.y = 0.0f; Svert2DfaceID[Sfacelist[Sface_start[x]]].plist[Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp].bary.z = 1.0f; Svert2DfaceID[Sfacelist[Sface_start[x]]].totalp++; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].Dface = tf - 1; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].bary.x = 0.0f; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].bary.y = 1.0f; Svert2DfaceID[g].plist[Svert2DfaceID[g].totalp].bary.z = 0.0f; Svert2DfaceID[g].totalp++; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].Dface = tf - 1; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].bary.x = 1.0f; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].bary.y = 0.0f; Svert2DfaceID[g1].plist[Svert2DfaceID[g1].totalp].bary.z = 0.0f; Svert2DfaceID[g1].totalp++; // tf++; } } if( ( ( DUTmtlgroup[x] == splines ) && ( splines >= 0 ) ) ) { Sface_end[x] = 0; Sface_start[x] = 0; } // it's a spline face //if (0==1) if( ( ( DUTmtlgroup[x] == splines ) && ( splines >= 0 ) ) ) { int g; // for (y=Sface_start[x];y 0 ) { VERT mid; SVMAP bary; bary.totalp = 0; bary.plist = NULL; // find_center(x,&avg,&avgb); avg_pnts( Sfacelist[Sface_start[x]], Sfacelist[Sface_start[x] + 2], &avg, &avgb ); if( ( Sface_end[x] - Sface_start[x] ) == 4 ) { int xx, yy; SVMAP avgb2; SVMAP avgbtmp; int matchcount = 0; avgb2.totalp = 0; avgb2.plist = NULL; avgbtmp.totalp = 0; avgbtmp.plist = NULL; avg_pnts( Sfacelist[Sface_start[x] + 1], Sfacelist[Sface_start[x] + 3], &avg, &avgb2 ); avgbtmp.plist = ( BARY * ) malloc( ( avgb.totalp + avgb2.totalp ) * sizeof( BARY ) ); avgbtmp.totalp = avgb.totalp + avgb2.totalp; for( xx = 0; xx < avgb.totalp; xx++ ) { avgbtmp.plist[matchcount] = avgb.plist[xx]; matchcount++; } for( xx = 0; xx < avgb2.totalp; xx++ ) { avgbtmp.plist[matchcount] = avgb2.plist[xx]; matchcount++; } avgbtmp.totalp = matchcount; avgb.plist = ( BARY * ) realloc( avgb.plist, avgbtmp.totalp * sizeof( BARY ) ); memcpy( avgb.plist, avgbtmp.plist, sizeof( BARY ) * avgbtmp.totalp ); avgb.totalp = avgbtmp.totalp; if( avgb2.plist != NULL ) Nfree( avgb2.plist ); if( avgbtmp.plist != NULL ) Nfree( avgbtmp.plist ); } cent = Stotalverts; Sedgeflag[Stotalverts] = 0; add_vert( avg, &avgb ); for( y = g; y < g + t - 1; y++ ) { // mid.x=(VS[Sfacelist[y]].x+VS[Sfacelist[y+1]].x)/2.0f; // mid.y=(VS[Sfacelist[y]].y+VS[Sfacelist[y+1]].y)/2.0f; // mid.z=(VS[Sfacelist[y]].z+VS[Sfacelist[y+1]].z)/2.0f; if( Sedgeflag[Sfacelist[y]] && Sedgeflag[Sfacelist[y + 1]] ) { Sedgeflag[Stotalverts] = 1; } else Sedgeflag[Stotalverts] = 0; avg_pnts( Sfacelist[y], Sfacelist[y + 1], &mid, &bary ); add_vert( mid, &bary ); tmpvertlist[totaltmpverts] = Stotalverts - 1; totaltmpverts++; Stag[Stotalverts - 1] = 1; // this is going to be merged } { // mid.x=(VS[Sfacelist[g+t-1]].x+VS[Sfacelist[g]].x)/2.0f; // mid.y=(VS[Sfacelist[g+t-1]].y+VS[Sfacelist[g]].y)/2.0f; // mid.z=(VS[Sfacelist[g+t-1]].z+VS[Sfacelist[g]].z)/2.0f; avg_pnts( Sfacelist[g + t - 1], Sfacelist[g], &mid, &bary ); if( Sedgeflag[Sfacelist[g + t - 1]] && Sedgeflag[Sfacelist[g]] ) { Sedgeflag[Stotalverts] = 1; } else Sedgeflag[Stotalverts] = 0; add_vert( mid, &bary ); tmpvertlist[totaltmpverts] = Stotalverts - 1; totaltmpverts++; Stag[Stotalverts - 1] = 1; // this is going to be merged } for( y = g + 1; y < g + t; y++ ) { int q; q = ( y - g ) - 1; add_quad( tmpvertlist[q], Sfacelist[y], tmpvertlist[q + 1], cent ); Skeepme[Stotalfaces - 1] = Skeepme[x]; } y = g + t - 1; add_quad( tmpvertlist[totaltmpverts - 1], Sfacelist[g], tmpvertlist[0], cent ); Skeepme[Stotalfaces - 1] = Skeepme[x]; Sface_start[x] = 0; Sface_end[x] = 0; if( bary.plist != NULL ) Nfree( bary.plist ); bary.plist = NULL; } if( avgb.plist != NULL ) Nfree( avgb.plist ); avgb.plist = NULL; } cleanup3( ); smoothit( ); } void displace_ht( ) { int xx; float scale; float freq; Smake_normals( ); for( xx = 0; xx < Stotalverts; xx++ ) { float n; freq = 9900.0f; scale = .002f; n = getnoise( VS[xx].x * freq, VS[xx].y * freq, VS[xx].z * freq ) - .5; VS[xx].x += Svn[xx].x * n * scale; VS[xx].y += Svn[xx].y * n * scale; VS[xx].z += Svn[xx].z * n * scale; } } void metanurb( int divs ) { int x, y, z; if( DUTtotalfaces > 0 ) { // initialize OVX for( x = 0; x < OVLIMIT; x++ ) for( y = 0; y < OVLIMIT; y++ ) for( z = 0; z < OVLIMIT; z++ ) { OVX[x][y][z].totalp = 0; } init_subdiv( ); Salloc( divs ); loadfaces( ); for( x = 0; x < divs; x++ ) { divide( ); } for( x = 0; x < OVLIMIT; x++ ) for( y = 0; y < OVLIMIT; y++ ) for( z = 0; z < OVLIMIT; z++ ) { if( OVX[x][y][z].totalp > 0 ) { Nfree( OVX[x][y][z].plist ); OVX[x][y][z].totalp = 0; } } build_pairs( ); // compress model #ifdef crap { WFTYPE tmpg; SVMAP *tmpb = NULL; int *SV2Dv; int *Sfv2Dfv; int *Sface2Dface; int tmptv1; SV2Dv = ( int * ) malloc( Stotalverts * sizeof( int ) ); for( x = 0; x < Stotalverts; x++ ) SV2Dv[x] = -1; Sfv2Dfv = ( int * ) malloc( Stotalfverts * sizeof( int ) ); for( x = 0; x < Stotalfverts; x++ ) Sfv2Dfv[x] = -1; Sface2Dface = ( int * ) malloc( Stotalfaces * sizeof( int ) ); for( x = 0; x < Stotalfaces; x++ ) Sface2Dface[x] = -1; init_geomWF( &tmpg ); for( x = 0; x < Stotalverts; x++ ) Stag[x] = 0; for( x = 0; x < Stotalfaces; x++ ) { if( Sface_end[x] - Sface_start[x] > 2 ) { for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int g; g = Sfacelist[y]; Stag[g] = 1; } } } tmpg.totalverts = 0; for( x = 0; x < Stotalverts; x++ ) if( Stag[x] == 1 ) { SV2Dv[x] = tmpg.totalverts; tmpg.totalverts++; } for( x = 0; x < Stotalfaces; x++ ) { if( Sface_end[x] - Sface_start[x] > 2 ) { Sface2Dface[x] = tmpg.totalfaces; for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int g; g = Sfacelist[y]; Sfv2Dfv[y] = tmpg.totalfverts; tmpg.totalfverts++; } tmpg.totalfaces++; } } tmptv1 = tmpg.totalverts; if( tmpb != NULL ) Nfree( tmpb ); tmpb = NULL; if( tmpg.totalverts > 0 ) { tmpb = ( SVMAP * ) malloc( ( tmpg.totalverts ) * sizeof( SVMAP ) ); for( x = 0; x < tmpg.totalverts; x++ ) { tmpb[x].totalp = 0; } for( x = 0; x < tmpg.totalverts; x++ ) tmpb[x].plist = NULL; } alloc_geomWF( &tmpg ); tmpg.totalfaces = 0; tmpg.totalverts = 0; tmpg.totalfverts = 0; for( x = 0; x < Stotalfaces; x++ ) { if( Sface_end[x] - Sface_start[x] > 2 ) { tmpg.face_start[tmpg.totalfaces] = tmpg.totalfverts; for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int g; g = Sfacelist[y]; tmpg.facelist[tmpg.totalfverts] = SV2Dv[g]; tmpg.totalfverts++; } tmpg.face_end[tmpg.totalfaces] = tmpg.totalfverts; tmpg.totalfaces++; } } tmpg.totalverts = 0; if( tmptv1 > 0 ) for( x = 0; x < Stotalverts; x++ ) if( Stag[x] == 1 ) { int yy; if( tmpg.totalverts >= tmptv1 ) { int error; error = 1; } tmpg.v[tmpg.totalverts] = VS[x]; if( tmpb[tmpg.totalverts].plist != NULL ) Nfree( tmpb[tmpg.totalverts].plist ); tmpb[tmpg.totalverts].plist = NULL; tmpb[tmpg.totalverts].totalp = Svert2DfaceID[x].totalp; if( Svert2DfaceID[x].totalp > 0 ) if( Svert2DfaceID[x].plist != NULL ) { tmpb[tmpg.totalverts].plist = ( BARY * ) malloc( tmpb[tmpg.totalverts].totalp * sizeof( BARY ) ); for( yy = 0; yy < Svert2DfaceID[x].totalp; yy++ ) tmpb[tmpg.totalverts].plist[yy] = Svert2DfaceID[x].plist[yy]; } tmpg.totalverts++; } // crash for( x = 0; x < S2totalverts; x++ ) { // if (Svert2DfaceID[x].totalp>0) if( Svert2DfaceID[x].plist != NULL ) Nfree( Svert2DfaceID[x].plist ); Svert2DfaceID[x].plist = NULL; } if( Svert2DfaceID != NULL ) Nfree( Svert2DfaceID ); Svert2DfaceID = NULL; if( Sface_start != NULL ) Nfree( Sface_start ); Sface_start = NULL; if( Sface_end != NULL ) Nfree( Sface_end ); Sface_end = NULL; if( Sfacelist != NULL ) Nfree( Sfacelist ); Sfacelist = NULL; if( VS != NULL ) Nfree( VS ); VS = NULL; if( Svn != NULL ) Nfree( Svn ); Svn = NULL; Svert2DfaceID = ( SVMAP * ) malloc( tmpg.totalverts * sizeof( SVMAP ) ); S2totalverts = tmpg.totalverts; for( x = 0; x < S2totalverts; x++ ) Svert2DfaceID[x].plist = NULL; VS = ( VERT * ) malloc( tmpg.totalverts * sizeof( VERT ) ); Svn = ( VERT * ) malloc( tmpg.totalverts * sizeof( VERT ) ); Sfacelist = ( int * ) malloc( tmpg.totalfverts * sizeof( int ) ); Sface_start = ( int * ) malloc( tmpg.totalfaces * sizeof( int ) ); Sface_end = ( int * ) malloc( tmpg.totalfaces * sizeof( int ) ); for( x = 0; x < tmpg.totalverts; x++ ) if( tmpb[x].plist != NULL ) if( tmpb[x].totalp > 0 ) { Svert2DfaceID[x].plist = ( BARY * ) malloc( tmpb[x].totalp * sizeof( BARY ) ); Svert2DfaceID[x].totalp = tmpb[x].totalp; for( y = 0; y < tmpb[x].totalp; y++ ) { Svert2DfaceID[x].plist[y] = tmpb[x].plist[y]; } } for( x = 0; x < tmpg.totalverts; x++ ) VS[x] = tmpg.v[x]; for( x = 0; x < tmpg.totalfaces; x++ ) { Sface_start[x] = tmpg.face_start[x]; Sface_end[x] = tmpg.face_end[x]; } for( x = 0; x < tmpg.totalfverts; x++ ) Sfacelist[x] = tmpg.facelist[x]; for( x = 0; x < Stotaledges * 2; x++ ) { Sedgepairs[x] = SV2Dv[Sedgepairs[x]]; } Nfree( SV2Dv ); Nfree( Sfv2Dfv ); Nfree( Sface2Dface ); Stotalfaces = tmpg.totalfaces; Stotalfverts = tmpg.totalfverts; Stotalverts = tmpg.totalverts; if( tmptv1 > 0 ) for( x = 0; x < tmptv1; x++ ) if( tmpb[x].plist != NULL ) { Nfree( tmpb[x].plist ); tmpb[x].plist = NULL; } if( tmpb != NULL ) Nfree( tmpb ); free_geomWF( &tmpg ); // tmpb=NULL; } //smoothit(); #endif metafixchains( ); if( Stotalverts > 0 ) { GMetaNurb = divs; if( SUBDrvcolor != NULL ) { Nfree( SUBDrvcolor ); SUBDrvcolor = NULL; } if( SUBDgvcolor != NULL ) { Nfree( SUBDgvcolor ); SUBDgvcolor = NULL; } if( SUBDbvcolor != NULL ) { Nfree( SUBDbvcolor ); SUBDbvcolor = NULL; } if( RSUBDrvcolor != NULL ) { Nfree( RSUBDrvcolor ); RSUBDrvcolor = NULL; } if( RSUBDgvcolor != NULL ) { Nfree( RSUBDgvcolor ); RSUBDgvcolor = NULL; } if( RSUBDbvcolor != NULL ) { Nfree( RSUBDbvcolor ); RSUBDbvcolor = NULL; } RSUBDrvcolor = ( float * ) malloc( Stotalverts * sizeof( float ) ); RSUBDgvcolor = ( float * ) malloc( Stotalverts * sizeof( float ) ); RSUBDbvcolor = ( float * ) malloc( Stotalverts * sizeof( float ) ); SUBDrvcolor = ( float * ) malloc( Stotalverts * sizeof( float ) ); SUBDgvcolor = ( float * ) malloc( Stotalverts * sizeof( float ) ); SUBDbvcolor = ( float * ) malloc( Stotalverts * sizeof( float ) ); for( x = 0; x < Stotalverts; x++ ) { SUBDrvcolor[x] = 0; SUBDgvcolor[x] = 0; SUBDbvcolor[x] = 0; RSUBDrvcolor[x] = 0; RSUBDgvcolor[x] = 0; RSUBDbvcolor[x] = 0; } } Dmake_normals( ); } else { if( Dtotalfaces > 0 ) DRAW_STATUS( "Xplant to original model (file too old)" ); } { int xx; int tff = 0; for( xx = 0; xx < Stotalfaces; xx++ ) { if( ( Sface_end[xx] - Sface_start[xx] ) > 0 ) tff++; } if( tff == 0 ) { SNfree( ); DRAW_STATUS( "Couldn't activate subdivs - no valid faces" ); GMetaNurb = 0; } } if( GMetaNurb > 0 ) calc_dominance( ); } void calc_dominance( void ) { int x, y, z; int tmpfaces[100]; int tmpfaces_hit[100]; if( Smtlgroup != NULL ) Nfree( Smtlgroup ); Smtlgroup = NULL; if( Stotalfaces > 0 ) Smtlgroup = ( int * ) malloc( Stotalfaces * sizeof( int ) ); if( Sdominant_faceID != NULL ) Nfree( Sdominant_faceID ); Sdominant_faceID = NULL; if( Stotalfaces > 0 ) Sdominant_faceID = ( int * ) malloc( Stotalfaces * sizeof( int ) ); if( Stotalfaces > 0 ) for( x = 0; x < Stotalfaces; x++ ) { // int bigv; // int big= -1; int total_tmpfaces = 0; int lastbig = -1; int big = -1; int bigv = -1; int lastbigv = -1; for( y = Sface_start[x]; y < Sface_end[x]; y++ ) { int g; int df; lastbig = -1; big = -1; bigv = -1; lastbigv = -1; g = Sfacelist[y]; for( z = 0; z < Svert2DfaceID[g].totalp; z++ ) { int zz; int found = 0; df = Svert2DfaceID[g].plist[z].Dface; for( zz = 0; zz < total_tmpfaces; zz++ ) { if( tmpfaces[zz] == df ) { found = 1; tmpfaces_hit[zz]++; } } if( found == 0 ) { tmpfaces[total_tmpfaces] = df; tmpfaces_hit[total_tmpfaces] = 0; total_tmpfaces++; } } } for( y = 0; y < total_tmpfaces; y++ ) { if( tmpfaces_hit[y] > big ) { int tmpbigv; tmpbigv = tmpfaces[y]; if( ( ( Dmtlgroup[tmpbigv] == head ) && ( head >= 0 ) ) || ( ( Dmtlgroup[tmpbigv] == beard ) && ( beard >= 0 ) ) || ( ( Dmtlgroup[tmpbigv] == eyebrow ) && ( eyebrow >= 0 ) ) || ( ( Dmtlgroup[tmpbigv] == eyelash ) && ( eyelash >= 0 ) ) ) { big = tmpfaces_hit[y]; bigv = tmpfaces[y]; } } } for( y = 0; y < total_tmpfaces; y++ ) { if( tmpfaces_hit[y] > lastbig ) { int tmpbigv; tmpbigv = tmpfaces[y]; { lastbig = tmpfaces_hit[y]; lastbigv = tmpfaces[y]; } } } if( ( bigv >= 0 ) && ( big >= 1 ) ) { Sdominant_faceID[x] = bigv; Smtlgroup[x] = Dmtlgroup[bigv]; } else if( lastbigv >= 0 ) { Smtlgroup[x] = Dmtlgroup[lastbigv]; Sdominant_faceID[x] = lastbigv; } } } void metafixchains( void ) { int x; for( x = 0; x < Dtotalverts; x++ ) //if (Skeepme[x]==1) { int gotone = 0; if( Svert2DfaceID[x].plist != NULL ) { if( gotone == 0 ) // if (Svert2DfaceID[x].plist[0].bary.z==1.0) { VERT a, delt; int pid = -1, y; int chain_id; int qq; // for (qq=0;qq=0) if( Dtag[x] ) { // a=Dv[Dfacelist[Dface_start[pid]+2]]; a = VS[x]; // chain_id=Dlink[Dfacelist[Dface_start[pid]]]; chain_id = Dlink[x]; delt.x = a.x - hair[chain_id].hv[0].x; delt.y = a.y - hair[chain_id].hv[0].y; delt.z = a.z - hair[chain_id].hv[0].z; for( y = 0; y < 15; y++ ) { hair[chain_id].hv[y].x += delt.x; hair[chain_id].hv[y].y += delt.y; hair[chain_id].hv[y].z += delt.z; hair[chain_id].resthv[y].x += delt.x; hair[chain_id].resthv[y].y += delt.y; hair[chain_id].resthv[y].z += delt.z; } v[chain_id] = hair[chain_id].hv[0]; } } } // if (0==1) // if (Svert2DfaceID[x].plist[0].bary.y==1.0) } } void metaunfixchains( void ) { int x; if( Stotalverts > 0 ) for( x = 0; x < Dtotalverts; x++ ) { int y; if( Dtag[x] ) { int y; VERT delt; int dl; dl = Dlink[x]; delt.x = Dv[x].x - hair[dl].hv[0].x; delt.y = Dv[x].y - hair[dl].hv[0].y; delt.z = Dv[x].z - hair[dl].hv[0].z; v[Dlink[x]] = Dv[x]; for( y = 0; y < 15; y++ ) { hair[dl].hv[y].x += delt.x; hair[dl].hv[y].y += delt.y; hair[dl].hv[y].z += delt.z; hair[dl].resthv[y].x += delt.x; hair[dl].resthv[y].y += delt.y; hair[dl].resthv[y].z += delt.z; } } } SNfree( ); } #ifdef crap void make_highres( WFTYPE * lores, WFYTYPE * highres, SUBDIVTYPE * subd ) { // first find closest lores face for each highres face using centroids // exclude faces with normals that are more than 45 degrees different // to be sure // compute a barycentric coord // to do this fast... maybe try projecting the point onto the poly before calculating weights? // we also want to construct a list of subdiv faces that are from the lores face // then later when we call tripoints, we're going to select a subface randomly } #endif