// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 static void draw_splines( int selunsel, int stat ); static void draw_hair( int selunsel, int stat ); BASEHAIR LOTSWFlastone; BASEHAIR LOTSWFlasthrest; int LOTSWFlastpid; CURVEINFO LOTSWFlastcinfo; void MTxformHandles( int x ); static void MTxformcontrolhair_nodyn( int x ); static void MTxformcontrolhair( int x); void threadedCall_XFORMCONTROL ( unsigned threadID, void* qqq); void MTxform_kernal ( void); void threadedCall_DODYN (unsigned threadID, void* qqq); void MTdodyn(int x); static void reset_rest2( int recalc_restlen ); #include void reset_noisespace( void ); #include "kdtree.h" //void draw_lotsWF2( int slg, int ind, VERT offs ); typedef struct { int *list; int total; int threadID; int done; } BUNCHLIST; void MTdodyn_kernal ( void); void threadedCall_DODYN (unsigned threadID, void* qqq); void MTdodyn(int x); void MTresample_guides_kernal ( MINIKERNAL *m); void threadedCall_MTRESAMPLE (unsigned threadID, void* qqq); void MTresample_guidesK(int hn,MINIKERNAL *m); void MTresample_guides_kernal ( MINIKERNAL *m) { int th; int inc; int count=0; int xxx; int done=0; void* threadGroup=NULL; int mult=0; int *list; int list_total=0; int x,y; int nn; BUNCHLISTK glist[SHAVE_MAX_THREADS]; if (total_splines==0) nn=totalguides; else nn=total_splines; list=NULL; if (nn>0) { int t=0; int pp; list = (int *) malloc (nn*sizeof(int)); for (x=0;x0) for (xxx=0;xxxlist=NULL; bb->list= (int *) malloc((list_total+1)*sizeof(int)); done=0; while (done==0) { bb->list[xx]=list[count]; count++; xx++; if ((xxx!=th-1) &&(xx==inc)) done=1; if (count==list_total) done=1; } bb->done=0; bb->total=xx; bb->threadID=xxx; bb->m=m; SHAVEstart_thread (GthreadGroup,threadedCall_MTRESAMPLE,(void*) bb); } // This will only work if the same thread group is not currently // in use anywhere else. // SHAVEwait_thread_group(GthreadGroup); //SHAVEend_thread_group(threadGroup); if (list_total>0) for (xxx=0;xxxdone=0; for (x=0;xtotal;x++) MTresample_guidesK(bb->list[x],bb->m); bb->done=1; x=0; } void MTresample_guidesK(int hn,MINIKERNAL *m) { BASEHAIR *get_guide; if (m->interpolation_type!=MESH_GROWTH) get_guide=&Shair[hn]; else get_guide=&hair[hn]; resize_base_hair_to_newguide(get_guide,&m->guides[hn],m->guide_segs); } void MTdodyn_kernal ( void) { int th; int inc; int count=0; int xxx; int done=0; void* threadGroup=NULL; int mult=0; int *list; int list_total=0; int x,y; int nn; BUNCHLIST glist[SHAVE_MAX_THREADS]; if (total_splines==0) nn=totalguides; else nn=total_splines; mkbounds( ); //#ifndef NOLIB for( y = 0; y < 5; y++ ) if( Gsurface_collide[y] == 1 ) DOCOLLIDE = 1; if( skull_sphere == -1 ) DOCOLLIDE = 0; // Cache Maya's force vectors for each guide vert. // MAYAcache_forces(0); for( x = 0; x < Dtotalverts; x++ ) { Dv[x].x /= ( float ) restBOUNDLENGTH; Dv[x].y /= ( float ) restBOUNDLENGTH; Dv[x].z /= ( float ) restBOUNDLENGTH; Drv[x].x /= ( float ) restBOUNDLENGTH; Drv[x].y /= ( float ) restBOUNDLENGTH; Drv[x].z /= ( float ) restBOUNDLENGTH; } for( x = 0; x < totalverts; x++ ) { v[x].x /= ( float ) restBOUNDLENGTH; v[x].y /= ( float ) restBOUNDLENGTH; v[x].z /= ( float ) restBOUNDLENGTH; } //#ifndef NOLIB if( DOCOLLIDE ) if( COLLISION_METHOD == 1 ) { make_normals( ); Dcalc_plane_eq( ); // norm is a unit vector setup_poly_vox( ); resize_poly_vox = 0; } if( DOCOLLIDE ) if( COLLISION_METHOD == 0 ) find_skulls( ); if (totalverts) { int xx; for( xx = 0; xx < Dtotalverts; xx++ ) { if( Dtag[xx] ) { float sl; x = Dlink[xx]; sl = hair[x].slider[8]; sl = SHAVEapply_VMAP( SHAVEID, xx, 8, sl ); hair[x].slider[8] = sl; sl = SHAVEapply_VMAP( SHAVEID, xx, 21, sl ); hair[x].slider[21] = sl; sl = SHAVEapply_VMAP( SHAVEID, xx, 40, sl ); hair[x].slider[40] = sl; // printf ("slider=%f\n",hair[x].slider[8]); } } } list = (int *) malloc (nn*sizeof(int)); if (total_splines==0) for (x=0;x0) { int t=0; int pp; th=SHAVEnum_processors(); if (list_total0) for (xxx=0;xxxlist= (int *) malloc((list_total+1)*sizeof(int)); done=0; while (done==0) { bb->list[xx]=list[count]; count++; xx++; if ((xxx!=th-1) &&(xx==inc)) done=1; if (count==list_total) done=1; } bb->done=0; bb->total=xx; bb->threadID=xxx; SHAVEstart_thread (GthreadGroup,threadedCall_DODYN,(void*) bb); } // This will only work if the same thread group is not currently // in use anywhere else. // SHAVEwait_thread_group(GthreadGroup); //SHAVEend_thread_group(threadGroup); if (list_total>0) for (xxx=0;xxxtotal;x++) MTdodyn(bb->list[x]); bb->done=1; x=0; } void MTxform_kernal ( void) { int th; int inc; int count=0; int xxx; int done=0; int mult=0; int *list; int list_total=0; int x; BUNCHLIST glist[SHAVE_MAX_THREADS]; list = (int *) malloc (totalguides*sizeof(int)); for (x=0;x0) { int t=0; int pp; th=SHAVEnum_processors(); if (list_total0) for (xxx=0;xxxdone=0; bb->list= (int *) malloc((list_total+1)*sizeof(int)); done=0; while (done==0) { bb->list[xx]=list[count]; count++; xx++; if ((xxx!=th-1) &&(xx==inc)) done=1; if (count==list_total) done=1; } bb->total=xx; bb->threadID=xxx; bb->done=0; SHAVEstart_thread (GthreadGroup,threadedCall_XFORMCONTROL,(void*) bb); } // This will only work if the same thread group is not currently // in use anywhere else. // SHAVEwait_thread_group(GthreadGroup); //SHAVEend_thread_group(threadGroup); if (list_total>0) for (xxx=0;xxxtotal;x++) MTxformcontrolhair(bb->list[x]); bb->done=1; x=0; } static void put_geomWF( WFTYPE * wf, CHNG *fname ) { FILE *fp = NULL; fp = MYfopen( fname, _T("w") ); if( fp ) { int x; fprintf( fp, "# object output by shave\n" ); for( x = 0; x < wf->totalverts; x++ ) fprintf( fp, "v %f %f %f\n", wf->v[x].x, wf->v[x].y, wf->v[x].z ); fprintf( fp, "usemtl default\n" ); for( x = 0; x < wf->totalfaces; x++ ) { int y; fprintf( fp, "f " ); for( y = wf->face_start[x]; y < wf->face_end[x]; y++ ) fprintf( fp, "%d ", wf->facelist[y] + 1 ); fprintf( fp, "\n" ); } fprintf( fp, "# end file\n" ); fclose( fp ); } } static void Gilluminate_strandINST( WFTYPE * pos, int ll, float hambient ) { VERT ret; VERT pos2; VERT lcolor; VERT drr; VERT lookvec; int q, x; //#ifndef RENDERLW for( q = 0; q < pos->totalverts; q++ ) { VERT shad; //#ifdef crap float cone = 1.0f; lcolor = LWlight[ll].color; if( LWlight[ll].trace == 1 ) { VERT vjunk; cone = calculate_light_cone( pos->v[q], ll, Gbacklighting, &vjunk ); } else { cone = 1.0f; } //shad=cast_shadows_lgt_simple(pos->v[q],ll); //shad.x=shad.x*(hambient)+(1.0f-hambient); //cone*=shad.x; cone *= 255; lcolor.x *= cone; lcolor.y *= cone; lcolor.z *= cone; pos->color[q] = lcolor; //#endif // shad=Gilluminate(pos->v[q],ll,Gbacklighting); // pos->color[q]=shad; } for( x = 0; x < pos->totalverts; x++ ) pos->v[x].z *= -1; for( x = 0; x < pos->totalverts; x++ ) SHAVEcoord_convertFROMSHAVE( &pos->v[x] ); for( x = 0; x < pos->totalverts; x++ ) { pos->color[x].x /= 255; pos->color[x].y /= 255; pos->color[x].z /= 255; } if( DOING_SWATCH == 0 ) SHAVEapply_illuminationWF( ll, pos ); for( x = 0; x < pos->totalverts; x++ ) { pos->color[x].x *= 255; pos->color[x].y *= 255; pos->color[x].z *= 255; } for( x = 0; x < pos->totalverts; x++ ) SHAVEcoord_convertTOSHAVE( &pos->v[x] ); for( x = 0; x < pos->totalverts; x++ ) { pos->v[x].z *= -1; } for( q = 0; q < pos->totalverts; q++ ) { VERT tmpv; lcolor = pos->color[q]; tmpv.x = pos->v[q].x + pos->vn[q].x * .1; tmpv.y = pos->v[q].y + pos->vn[q].y * .1; tmpv.z = pos->v[q].z + pos->vn[q].z * .1; ret = cast_shadows_lgt_simpleINST( tmpv, ll ); ret.x *= hambient; ret.y *= hambient; ret.z *= hambient; ret.x += ( 1.0f - hambient ); ret.y += ( 1.0f - hambient ); ret.z += ( 1.0f - hambient ); ret.x *= lcolor.x; ret.y *= lcolor.y; ret.z *= lcolor.z; //ret=lcolor; pos->color[q] = ret; } } static VERT Gilluminate( VERT pos, int ll, float hambient ) { VERT ret; VERT pos2; VERT lcolor; VERT drr; VERT lookvec; //#ifndef RENDERLW float cone = 1.0f; drr.x = LWlight[ll].wpos.x - pos.x; drr.y = LWlight[ll].wpos.y - pos.y; drr.z = LWlight[ll].wpos.z - pos.z; drr = Vnorm( drr ); lcolor = LWlight[ll].color; //if (Gtrace==0) if( LWlight[ll].trace == 0 ) { //cone=calculate_light_cone(pos,ll,Gbacklighting); } else { cone = 1.0f; } lcolor.x *= cone; lcolor.y *= cone; lcolor.z *= cone; //printf ("Gbacklighting== %f\n",Gbacklighting); //SHAVEcoord_convertFROMSHAVE(&pos); pos.z *= -1; drr.z *= -1; SHAVEcoord_convertFROMSHAVE( &drr ); SHAVEcoord_convertFROMSHAVE( &pos ); if( DOING_SWATCH == 0 ) lcolor = SHAVEapply_illumination( ll, pos, drr, lcolor ); SHAVEcoord_convertTOSHAVE( &pos ); SHAVEcoord_convertFROMSHAVE( &drr ); pos.z *= -1; drr.z *= -1; //SHAVEcoord_convertTOSHAVE(&drr); //lcolor.x= lcolor.x*Gbacklighting+LWlight[ll].color.x*(1.0f-Gbacklighting); //lcolor.y= lcolor.y*Gbacklighting+lcolor.y*(1.0f-Gbacklighting); //lcolor.z= lcolor.z*Gbacklighting+lcolor.z*(1.0f-Gbacklighting); //junk=Gsa->illuminate(LWlight[ll].id,tpos,tdir,tclr); ret = cast_shadows_lgt_simple( pos, ll ); ret.x *= hambient; ret.y *= hambient; ret.z *= hambient; ret.x += ( 1.0f - hambient ); ret.y += ( 1.0f - hambient ); ret.z += ( 1.0f - hambient ); ret.x *= lcolor.x; ret.y *= lcolor.y; ret.z *= lcolor.z; return ( ret ); } static void MTxformcontrolhair_nodyn( int x ) { int g; float uu = 0; uu = 1.0f; // make_normals( ); //for (x=0;x= 0; g-- ) { hair[x].hv[g].x -= hair[x].hv[0].x; hair[x].hv[g].y -= hair[x].hv[0].y; hair[x].hv[g].z -= hair[x].hv[0].z; hair[x].hv[g].x += v[x].x; hair[x].hv[g].y += v[x].y; hair[x].hv[g].z += v[x].z; } } else { Sthishair[x] = Shair[x]; for( g = 14; g >= 0; g-- ) { int q; q = facelist[face_end[splinelist[x]] - 1]; Shair[x].hv[g].x -= Shair[x].hv[0].x; Shair[x].hv[g].y -= Shair[x].hv[0].y; Shair[x].hv[g].z -= Shair[x].hv[0].z; Shair[x].hv[g].x += v[q].x; Shair[x].hv[g].y += v[q].y; Shair[x].hv[g].z += v[q].z; } Shair[x].restlength=VdistanceK(Sresthair[x].resthv[0],Sresthair[x].resthv[1]); } MTxformHandles(x ); } static void xformcontrolhair_nodyn( void ) { int x; int g; float uu = 0; uu = 1.0f; make_normals( ); //for (x=0;x= 0; g-- ) { hair[x].hv[g].x -= hair[x].hv[0].x; hair[x].hv[g].y -= hair[x].hv[0].y; hair[x].hv[g].z -= hair[x].hv[0].z; hair[x].hv[g].x += v[x].x; hair[x].hv[g].y += v[x].y; hair[x].hv[g].z += v[x].z; } } for( x = 0; x < total_splines; x++ ) Sthishair[x] = Shair[x]; for( x = 0; x < total_splines; x++ ) { for( g = 14; g >= 0; g-- ) { int q; q = facelist[face_end[splinelist[x]] - 1]; Shair[x].hv[g].x -= Shair[x].hv[0].x; Shair[x].hv[g].y -= Shair[x].hv[0].y; Shair[x].hv[g].z -= Shair[x].hv[0].z; Shair[x].hv[g].x += v[q].x; Shair[x].hv[g].y += v[q].y; Shair[x].hv[g].z += v[q].z; } } xformHandles( ); } static void getframe( void ) { // if (cursamp!=0) xformcontrolhair_nodyn( ); //_nodyn(); // else xformcontrolhair(); //xformcontrolhair(); // cursamp++; } static void mkbounds( void ); static void xforminst( int num ) { int x = 0; Matrix pm; //BASEHAIR h; float scal = 0.0f; int l1 = 0, l2 = 0; VERT *col, *vel; VERT offs; float sc = 0.0f; int cc = 0; cc = Gcurpass % LOCAL_PASSES[matrixhair.slg]; Jsrand( ( unsigned long ) ( cc * 65535 + num * 2134 + matrixhair.vid * 5192 ) ); mixitup( ); offs.x = ( float ) drand98( ) - .5f; offs.z = ( float ) drand98( ) - .5f; offs.y = 0; if( matrixhair.slg != 4 ) mk_polymat( pm, matrixhair.pid ); if( matrixhair.slg == 4 ) Smk_polymat( pm, matrixhair.pid ); offs = vxm( pm, offs ); offs = Vnorm( offs ); if( matrixhair.slg != 4 ) sc = Distance( v[facelist[face_start[matrixhair.pid]]], v[facelist[face_start[matrixhair.pid] + 1]] ); if( matrixhair.slg == 4 ) sc = matrixhair.restlength * ( 56.0 / 15.0 ); sc *= ( float ) drand98( ); offs.x *= sc; offs.y *= sc; offs.z *= sc; scal = ( matrixhair.restlength * 56.0f ) / matrixhair.spany; //scal=1; for( x = 0; x < freeze.totalverts; x++ ) { float w; l1 = freeze.envelope[x].link1; l2 = freeze.envelope[x].link2; freeze.uv[x].x = matrixhair.uu; freeze.uv[x].y = matrixhair.vv; // freezetmp.uv[x].x =matrixhair.uu; // freezetmp.uv[x].y = matrixhair.vv; // freezetmp1.uv[x].x =matrixhair.uu; // freezetmp1.uv[x].y = matrixhair.vv; // freezetmp2.uv[x].x =matrixhair.uu; // freezetmp2.uv[x].y = matrixhair.vv; col = &matrixhair.color[l1]; freezetmp1.Rrvcolor[x] = col->x; // *255.0f; freezetmp1.Rgvcolor[x] = col->y; // *255.0f; freezetmp1.Rbvcolor[x] = col->z; // *255.0f; vel = &matrixhair.velocity[l1]; freezetmp1.velocity[x].x = vel->x; freezetmp1.velocity[x].y = vel->y; freezetmp1.velocity[x].z = vel->z; // freezetmp1.uv[x].x=; // freezetmp1.uv[x].y=; // freezetmp1.uv[x].z=; { int l1, l2; VERT *col, *vel, *pos, *v9, *v10; l1 = freeze.envelope[x].link1; l2 = freeze.envelope[x].link2; v9 = &freeze.v[x]; pos = &matrixhair.restpos[l1]; v10 = &freezetmp1.v[x]; v10->x = v9->x - pos->x; v10->y = v9->y - pos->y; v10->z = v9->z - pos->z; // freezetmp1.v[x]=vxm(matrixhair.rest2zero[freeze.envelope[x].link1],freezetmp1.v[x]); //w=sliders[20][matrixhair.slg].value; //w=ma; w = matrixhair.cutlength * matrixhair.thickness; // w = scal * matrixhair.thickness * ( .3 ); /////w*=(matrixhair.restlength/(float)BOUNDLENGTH)*1500.0f; // freezetmp1.v[x].x*=.0002*w; // freezetmp1.v[x].z*=.0002*w; v10->x *= w; v10->y *= scal; v10->z *= w; { VERT *wpp; VERT tmpp; wpp = &matrixhair.worldpos[l1]; tmpp = vxm( matrixhair.zero2world[l1], freezetmp1.v[x] ); v10->x = tmpp.x; v10->y = tmpp.y; v10->z = tmpp.z; v10->x += wpp->x; v10->y += wpp->y; v10->z += wpp->z; } if( num > 0 ) if( matrixhair.dreadcount > 0 ) { float vs; vs = ( ( float ) l1 / 56.0 ); // vs=1.0f-vs; // vs*=vs; // vs=1.0f-vs; vs = ( ( float ) vs ) * matrixhair.dreadtip + ( 1.0f - ( float ) vs ) * matrixhair.dreadroot; // if (vs>1.0) vs=1.0f; if( vs < 0 ) vs = 0; // vs*=vs; v10->x += vs * offs.x; v10->y += vs * offs.y; v10->z += vs * offs.z; } } } for( x = 0; x < freeze.totalverts; x++ ) { float w; VERT *v9, *vel, *col; l1 = freeze.envelope[x].link1; l2 = freeze.envelope[x].link2; v9 = &freezetmp2.v[x]; //if (freeze.textoggle==1) // global texturing { freezetmp2.velocity[x].x = matrixhair.velocity[l2].x; freezetmp2.velocity[x].y = matrixhair.velocity[l2].y; freezetmp2.velocity[x].z = matrixhair.velocity[l2].z; freezetmp2.Rrvcolor[x] = matrixhair.color[l2].x; //*255.0f; freezetmp2.Rgvcolor[x] = matrixhair.color[l2].y; //*255.0f; freezetmp2.Rbvcolor[x] = matrixhair.color[l2].z; //55.0f; } v9->x = freeze.v[x].x - matrixhair.restpos[l2].x; v9->y = freeze.v[x].y - matrixhair.restpos[l2].y; v9->z = freeze.v[x].z - matrixhair.restpos[l2].z; // freezetmp2.v[x]=vxm(matrixhair.rest2zero[freeze.envelope[x].link2],freezetmp2.v[x]); //w=sliders[20][matrixhair.slg].value; //w*=scal; //w=sliders[20][matrixhair.slg].value; //w=matrixhair.slider[20]; // //w=matrixhair.cutlength*matrixhair.thickness; w = scal; w = scal * matrixhair.thickness; w = scal * matrixhair.thickness; w = scal * matrixhair.thickness * ( .3 ); ////w*=(matrixhair.restlength/(float)BOUNDLENGTH)*1500.0f; v9->x *= w; v9->y *= scal; v9->z *= w; freezetmp2.v[x] = vxm( matrixhair.zero2world[l2], freezetmp2.v[x] ); v9->x += matrixhair.worldpos[l2].x; v9->y += matrixhair.worldpos[l2].y; v9->z += matrixhair.worldpos[l2].z; if( matrixhair.dreadcount > 0 ) if( num > 0 ) { float vs; vs = ( freeze.envelope[x].link2 / 56.0 ); vs = ( ( float ) vs ) * matrixhair.dreadtip + ( 1.0f - ( float ) vs ) * matrixhair.dreadroot; if( vs > 1.0 ) vs = 1.0f; if( vs < 0 ) vs = 0; // vs*=vs; vs = 1.0f - vs; vs *= vs; vs = 1.0f - vs; v9->x += vs * offs.x; v9->y += vs * offs.y; v9->z += vs * offs.z; } } // now blend them for( x = 0; x < freeze.totalverts; x++ ) { int slg; float fe; VERT *v9; VERT *vel, *vel1, *vel2; vel = &freezetmp.velocity[x]; vel1 = &freezetmp1.velocity[x]; vel2 = &freezetmp2.velocity[x]; fe = freeze.envelope[x].v; // if (freeze.textoggle==1) // global texturing { freezetmp.Rrvcolor[x] = ( freezetmp1.Rrvcolor[x] * ( 1.0f - fe ) + freezetmp2.Rrvcolor[x] * fe ) / 255.0f; freezetmp.Rgvcolor[x] = ( freezetmp1.Rgvcolor[x] * ( 1.0f - fe ) + freezetmp2.Rgvcolor[x] * fe ) / 255.0f; freezetmp.Rbvcolor[x] = ( freezetmp1.Rbvcolor[x] * ( 1.0f - fe ) + freezetmp2.Rbvcolor[x] * fe ) / 255.0f; // freeze.Rrvcolor[x]=freezetmp.Rrvcolor[x]; // freeze.Rgvcolor[x]=freezetmp.Rgvcolor[x]; // freeze.Rbvcolor[x]=freezetmp.Rbvcolor[x]; vel->x = vel1->x * ( 1.0f - fe ) + vel2->x * fe; vel->y = vel1->y * ( 1.0f - fe ) + vel2->y * fe; vel->z = vel1->z * ( 1.0f - fe ) + vel2->z * fe; } slg = matrixhair.slg; { VERT *va, *vb, *vc; va = &freezetmp.v[x]; vb = &freezetmp1.v[x]; vc = &freezetmp2.v[x]; va->x = vb->x * ( 1.0f - fe ) + vc->x * ( fe ); va->y = vb->y * ( 1.0f - fe ) + vc->y * ( fe ); va->z = vb->z * ( 1.0f - fe ) + vc->z * ( fe ); } //freezetmp.v[x]=freezetmp2.v[x]; } { int clock = 0; ///// bad! freezetmp.mtlgroup=(int)matrixhair.mtl; // printf ("testing for colorlock\n"); //for (x=0;x=0) clock=1; //if (clock==1) //for (x=0;x 0 ) { // hair[g].hv[0]=v[g]; // resthair[g].hv[0]=v[g]; // thishair[g].hv[0]=v[g]; // hair[g].hv[0]=v[g]; for( x = 1; x < 15; x++ ) { int p; VERT xx, yy, zz, rxx, ryy, rzz; float d, d1; p = hair[g].pfID[x]; // this is the poly it's tied to if( p != -1 ) { int q, q1; q = Dfacelist[Dface_start[p]]; // this is the x axis q1 = Dfacelist[Dface_start[p] + 1]; xx.x = Dv[q1].x - Dv[q].x; xx.y = Dv[q1].y - Dv[q].y; xx.z = Dv[q1].z - Dv[q].z; q = Dfacelist[Dface_start[p]]; // this is the z axis q1 = Dfacelist[Dface_start[p] + 2]; zz.x = Dv[q1].x - Dv[q].x; zz.y = Dv[q1].y - Dv[q].y; zz.z = Dv[q1].z - Dv[q].z; d = fsqrt( xx.x * xx.x + xx.y * xx.y + xx.z * xx.z ); xx = Vnorm( xx ); zz = Vnorm( zz ); yy = Vcross( xx, zz ); yy = Vnorm( yy ); zz = Vcross( xx, yy ); zz = Vnorm( zz ); // now the rest pose q = Dfacelist[Dface_start[p]]; // this is the x axis q1 = Dfacelist[Dface_start[p] + 1]; rxx.x = Drv[q1].x - Drv[q].x; rxx.y = Drv[q1].y - Drv[q].y; rxx.z = Drv[q1].z - Drv[q].z; q = Dfacelist[Dface_start[p]]; // this is the z axis q1 = Dfacelist[Dface_start[p] + 2]; rzz.x = Drv[q1].x - Drv[q].x; rzz.y = Drv[q1].y - Drv[q].y; rzz.z = Drv[q1].z - Drv[q].z; d1 = fsqrt( rxx.x * rxx.x + rxx.y * rxx.y + rxx.z * rxx.z ); rxx = Vnorm( rxx ); rzz = Vnorm( rzz ); ryy = Vcross( rxx, rzz ); ryy = Vnorm( ryy ); rzz = Vcross( rxx, ryy ); rzz = Vnorm( rzz ); // now make the matricies mkmatrix( tmpmat, rxx, ryy, rzz, Drv[q] ); inverse( tmpmat, rest2zero ); mkmatrix( zero2world, xx, yy, zz, Dv[q] ); //#ifdef LIB // d=1.0f; // d1=1.0f; //#endif xx = hair[g].resthv[x]; xx.x -= Drv[q].x; xx.y -= Drv[q].y; xx.z -= Drv[q].z; if( d1 != 0 ) { // xx.x/=d1; // xx.y/=d1; // xx.z/=d1; } xx = vxm( rest2zero, xx ); xx = vxm( zero2world, xx ); if( d != 0 ) { // xx.x*=d; // xx.y*=d; // xx.z*=d; } xx.x += Dv[q].x; xx.y += Dv[q].y; xx.z += Dv[q].z; hair[g].hv[x] = xx; } // p!= -1 } // x - hv loop 0<15 } // doit //#endif } static void Srestore_locked_hair( int g ) { int x; int doit = 0; Matrix tmpmat, rest2zero, zero2world; for( x = 1; x < 15; x++ ) { if( Sresthair[g].pfID[x] != -1 ) // it's locked doit = 1; } //#ifdef NOLIB //for (x=1;x<15;x++) // { // if (resthair[g].pfID[x]!= -1) // hair[g].hv[x]=resthair[g].hv[x]; // } //#endif //#ifdef LIB if( doit == 1 ) if( Shair[g].restlength > 0 ) { // hair[g].hv[0]=v[g]; // resthair[g].hv[0]=v[g]; // thishair[g].hv[0]=v[g]; // hair[g].hv[0]=v[g]; for( x = 1; x < 15; x++ ) { int p; VERT xx, yy, zz, rxx, ryy, rzz; float d, d1; p = Sresthair[g].pfID[x]; // this is the poly it's tied to if( p != -1 ) { int q, q1; q = Dfacelist[Dface_start[p]]; // this is the x axis q1 = Dfacelist[Dface_start[p] + 1]; xx.x = Dv[q1].x - Dv[q].x; xx.y = Dv[q1].y - Dv[q].y; xx.z = Dv[q1].z - Dv[q].z; q = Dfacelist[Dface_start[p]]; // this is the z axis q1 = Dfacelist[Dface_start[p] + 2]; zz.x = Dv[q1].x - Dv[q].x; zz.y = Dv[q1].y - Dv[q].y; zz.z = Dv[q1].z - Dv[q].z; d = fsqrt( xx.x * xx.x + xx.y * xx.y + xx.z * xx.z ); xx = Vnorm( xx ); zz = Vnorm( zz ); yy = Vcross( xx, zz ); yy = Vnorm( yy ); zz = Vcross( xx, yy ); zz = Vnorm( zz ); // now the rest pose q = Dfacelist[Dface_start[p]]; // this is the x axis q1 = Dfacelist[Dface_start[p] + 1]; rxx.x = Drv[q1].x - Drv[q].x; rxx.y = Drv[q1].y - Drv[q].y; rxx.z = Drv[q1].z - Drv[q].z; q = Dfacelist[Dface_start[p]]; // this is the z axis q1 = Dfacelist[Dface_start[p] + 2]; rzz.x = Drv[q1].x - Drv[q].x; rzz.y = Drv[q1].y - Drv[q].y; rzz.z = Drv[q1].z - Drv[q].z; d1 = fsqrt( rxx.x * rxx.x + rxx.y * rxx.y + rxx.z * rxx.z ); rxx = Vnorm( rxx ); rzz = Vnorm( rzz ); ryy = Vcross( rxx, rzz ); ryy = Vnorm( ryy ); rzz = Vcross( rxx, ryy ); rzz = Vnorm( rzz ); // now make the matricies mkmatrix( tmpmat, rxx, ryy, rzz, Drv[q] ); inverse( tmpmat, rest2zero ); mkmatrix( zero2world, xx, yy, zz, Dv[q] ); //#ifdef LIB // d=1.0f; // d1=1.0f; //#endif xx = Sresthair[g].hv[x]; xx.x -= Drv[q].x; xx.y -= Drv[q].y; xx.z -= Drv[q].z; if( d1 != 0 ) { // xx.x/=d1; // xx.y/=d1; // xx.z/=d1; } xx = vxm( rest2zero, xx ); xx = vxm( zero2world, xx ); if( d != 0 ) { // xx.x*=d; // xx.y*=d; // xx.z*=d; } xx.x += Dv[q].x; xx.y += Dv[q].y; xx.z += Dv[q].z; Shair[g].hv[x] = xx; } // p!= -1 } // x - hv loop 0<15 } // doit //#endif } static void restore_locked( void ) { int x; for( x = 0; x < totalverts; x++ ) { restore_locked_hair( x ); } } static void swap( float a, float b ) { float c; c = b; b = a; a = c; } static void weight_polys( void ) { int x; int y; // float *tmpwgt; // int *tmpcnt; double big = 0; double sz[3]; double area; sz[0] = 0; sz[1] = 0; sz[2] = 0; // tmpwgt=(float *) malloc (totalverts*sizeof(float)); // tmpcnt=(int *) malloc (totalverts*sizeof(int)); // for (x=0;x 2 ) { int q = 0; int qq = 0, qq1, qq2; int qqa, qqb, qqc; qq = facelist[face_start[x]]; qq1 = facelist[face_start[x] + 1]; qq2 = facelist[face_start[x] + 2]; sz[0] = 0; sz[1] = 0; sz[2] = 0; //if (qq a ) swap( b, a ); if( c > a ) swap( c, a ); if( c > b ) swap( c, b ); if( c < ( a - b ) ) c = ( a - b ); // Calculate the area. tmp1 = a + b + c; tmp2 = b - a + c; tmp3 = a - b + c; tmp4 = b - c + a; area = 0.25 * sqrt( tmp1 * tmp2 * tmp3 * tmp4 ); //#endif } if( big < area ) big = area; // big+=sz; } } } // big*=big; for( x = 0; x < totalfaces; x++ ) if( ( face_end[x] - face_start[x] ) > 2 ) { int q = 0; int qq = 0, qq1, qq2; qq = facelist[face_start[x]]; qq1 = facelist[face_start[x] + 1]; qq2 = facelist[face_start[x] + 2]; sz[0] = 0; sz[1] = 0; sz[2] = 0; //if (qq a ) swap( b, a ); if( c > a ) swap( c, a ); if( c > b ) swap( c, b ); //assert( c >= ( a - b ) ); if( c < ( a - b ) ) c = ( a - b ); // Calculate the area. tmp1 = a + b + c; tmp2 = b - a + c; tmp3 = a - b + c; tmp4 = b - c + a; area = 0.25 * sqrt( tmp1 * tmp2 * tmp3 * tmp4 ); //#endif //area *=area; if( big > 0.0 ) poly_weight[x] = ( area ) / big; // if (x<1000) printf ("%f %f %f poly_weight[%d]=%f\n",a,b,c,x,poly_weight[x]);fflush(stdout); } // if (poly_weight[x]>1.0) // poly_weight[x]=1.0f; // poly_weight[x]=1.0f; } else poly_weight[x] = 0.0f; } //Nfree(tmpwgt); //Nfree(tmpcnt); //printf ("big = %f\n",big); if( totalverts > 0 ) if( big < 0.00000001f ) DEGENERATE_OBJECT = 1; for( x = 0; x < total_splines; x++ ) { // if (Shair[x].restlength==0.0f) DEGENERATE_OBJECT=1; // if (Sresthair[x].restlength==0.0f) DEGENERATE_OBJECT=1; } } static void Satten_len( void ); static void atten_len( void ) { int x, y; float big; float maxlen_before = 0, maxlen_after = 0; float *ww = NULL; int t; if( splines < 0 ) { ww = ( float * ) malloc( sizeof( float ) * totalverts ); weight_polys( ); big = 0; for( x = 0; x < totalverts; x++ ) ww[x] = 10000; for( x = 0; x < totalfaces; x++ ) for( y = face_start[x]; y < face_end[x]; y++ ) { int g; g = facelist[y]; if( ww[g] > ( float ) poly_weight[x] ) ww[g] = poly_weight[x]; } for( t = 0; t < 10; t++ ) { for( x = 0; x < totalfaces; x++ ) for( y = face_start[x]; y < face_end[x]; y++ ) { int g; g = facelist[y]; if( ww[g] > poly_weight[x] ) ww[g] = poly_weight[x]; } for( x = 0; x < totalfaces; x++ ) { float pw = 0; for( y = face_start[x]; y < face_end[x]; y++ ) { int g; g = facelist[y]; pw += ww[g]; } pw /= ( float ) ( face_end[x] - face_start[x] ); poly_weight[x] = pw; } } for( x = 0; x < totalverts; x++ ) ww[x] = sqrt( ww[x] ); for( x = 0; x < totalverts; x++ ) if( ww[x] > big ) big = ww[x]; if( big > 0 ) for( x = 0; x < totalverts; x++ ) ww[x] /= big; for( x = 0; x < totalverts; x++ ) ww[x] = ww[x] * .4; for( x = 0; x < totalverts; x++ ) if( hair[x].select[0] ) if( group_stat[hair[x].mtl] == 0 ) if( hair[x].restlength > maxlen_before ) maxlen_before = hair[x].restlength; for( x = 0; x < totalverts; x++ ) if( hair[x].select[0] ) if( group_stat[hair[x].mtl] == 0 ) { int t; hair[x].restlength *= ( .05 + pow( ww[x], 1.005 ) ) * 2; //*15.5f; for( y = 1; y < 15; y++ ) { hair[x].hv[y].x -= hair[x].hv[0].x; hair[x].hv[y].y -= hair[x].hv[0].y; hair[x].hv[y].z -= hair[x].hv[0].z; hair[x].hv[y].x *= ( .05 + pow( ww[x], 1.005 ) ) * 2; //*15.5f; hair[x].hv[y].y *= ( .05 + pow( ww[x], 1.005 ) ) * 2; //*15.5f; hair[x].hv[y].z *= ( .05 + pow( ww[x], 1.005 ) ) * 2; //*15.5f; hair[x].hv[y].x += hair[x].hv[0].x; hair[x].hv[y].y += hair[x].hv[0].y; hair[x].hv[y].z += hair[x].hv[0].z; } //if (hair[x].restlength<0.0001f) // if( hair[x].select[0] ) // { // for( t = 0; t < 15; t++ ) // hair[x].hv[t]=v[x]; // hair[x].restlength=0.0f; // hair[x].select[0]=0; // } if( hair[x].restlength < 0.0001f ) { //int y; VERT qq; hair[x].restlength = 0.0f; hair[x].sparerestlength = 0.0f; qq = v[x]; #ifdef MAX3D //qq.z*= -1.0f; #endif for( y = 0; y < 15; y++ ) hair[x].hv[y] = qq; } for( t = 0; t < 15; t++ ) hair[x].resthv[t] = hair[x].hv[t]; } for( x = 0; x < totalverts; x++ ) if( hair[x].select[0] ) if( group_stat[hair[x].mtl] == 0 ) if( hair[x].restlength > maxlen_after ) maxlen_after = hair[x].restlength; //if (maxlen_after>0) //SOFTscale_select((float)(maxlen_before/maxlen_after)); Nfree( ww ); weight_polys( ); } else Satten_len( ); } void Dweight_polys( void ); static void Satten_len( void ) { int x, y; float big; float maxlen_before = 0, maxlen_after = 0; float *ww = NULL; float *hits = NULL; int t; make_spline_normals( ); Dpoly_weight = ( float * ) malloc( sizeof( float ) * Dtotalfaces ); ww = ( float * ) malloc( sizeof( float ) * Dtotalverts ); hits = ( float * ) malloc( sizeof( float ) * Dtotalverts ); Dweight_polys( ); big = 0; for( x = 0; x < Dtotalverts; x++ ) ww[x] = 0.0f; for( x = 0; x < Dtotalverts; x++ ) hits[x] = 0.0f; for( x = 0; x < Dtotalfaces; x++ ) for( y = Dface_start[x]; y < Dface_end[x]; y++ ) { int g; g = Dfacelist[y]; ww[g] += Dpoly_weight[x]; hits[g] += 1.0f; } for( x = 0; x < Dtotalverts; x++ ) ww[x] /= hits[x]; for( x = 0; x < total_splines; x++ ) { for( y = 1; y < 15; y++ ) { Shair[x].hv[y].x -= Shair[x].hv[0].x; Shair[x].hv[y].y -= Shair[x].hv[0].y; Shair[x].hv[y].z -= Shair[x].hv[0].z; Shair[x].hv[y].x *= ww[Shair[x].pid]; Shair[x].hv[y].y *= ww[Shair[x].pid]; Shair[x].hv[y].z *= ww[Shair[x].pid]; Shair[x].hv[y].x += Shair[x].hv[0].x; Shair[x].hv[y].y += Shair[x].hv[0].y; Shair[x].hv[y].z += Shair[x].hv[0].z; } } if( ww ) free( ww ); if( Dpoly_weight ) free( Dpoly_weight ); if( hits ) free( hits ); } static float distance( VERT a, VERT b ); static VERT Vnorm( VERT v ); static void mkbounds( void ); static void xplant( CHNG file[555] ) { } static void WFxplant( CHNG file[555] ) { BASEHAIR base; //,restbase,noisebase; int oldmap[555]; int matmap[555]; int oldtotalverts; BASEHAIR *oldhair; // BASEHAIR *oldresthair; int oldsplines = -1; int *oldface_start = NULL; int *oldface_end = NULL; int *oldfacelist = NULL; int oldtotalfaces; int oldtotalfverts; int old_cnt[6]; int old_shadcnt[6]; int old_passes[6]; int x, y; float BIG; int vid; int oldmtl = -1; int oldskull_sphere = -1; //printf ("doing xplant\n"); reset_noisespace( ); //replace_rest(); global_lastID = -1; clear_uvsets( ); Gtotal_splinelocks= 0; for( x = 0; x < 555; x++ ) oldmap[x] = -1; for( x = 0; x < 555; x++ ) matmap[x] = -1; for( x = 0; x < 5; x++ ) old_cnt[x] = LOCAL_CNT[x]; for( x = 0; x < 5; x++ ) old_shadcnt[x] = LOCAL_SHADCNT[x]; for( x = 0; x < 5; x++ ) old_passes[x] = LOCAL_PASSES[x]; // dissable locking for( x = 0; x < totalverts; x++ ) { for( y = 0; y < 15; y++ ) { { hair[x].pfID[y] = -1; // resthair[x].pfID[y]= -1; } } } for( x = 0; x < total_splines; x++ ) for( y = 0; y < 15; y++ ) { { Shair[x].pfID[y] = -1; Sresthair[x].pfID[y] = -1; } } oldskull_sphere = skull_sphere; oldtotalverts = totalverts; oldtotalfverts = totalfverts; oldtotalfaces = totalfaces; oldsplines = splines; oldmtl = head; oldhair = ( BASEHAIR * ) malloc( totalverts * sizeof( BASEHAIR ) ); // oldresthair=(BASEHAIR *) malloc (totalverts*sizeof(BASEHAIR)); oldfacelist = ( int * ) malloc( totalfverts * sizeof( int ) ); oldface_start = ( int * ) malloc( totalfaces * sizeof( int ) ); oldface_end = ( int * ) malloc( totalfaces * sizeof( int ) ); for( x = 0; x < totalverts; x++ ) { int y; memcpy( &oldhair[x], &hair[x], sizeof( BASEHAIR ) ); // memcpy(&oldresthair[x],&resthair[x],sizeof(BASEHAIR)); } for( x = 0; x < totalfverts; x++ ) oldfacelist[x] = facelist[x]; for( x = 0; x < totalfaces; x++ ) oldface_start[x] = face_start[x]; for( x = 0; x < totalfaces; x++ ) oldface_end[x] = face_end[x]; oldtotalverts = totalverts; for( x = 0; x < 5; x++ ) old_cnt[x] = LOCAL_CNT[x]; for( x = 0; x < 5; x++ ) old_shadcnt[x] = LOCAL_SHADCNT[x]; // SHAVEclear_stack( ); getobj( file ); // get the new model //printf ("planted hair on new object\n"); if( COLLISION_METHOD == 1 ) if( DOCOLLIDE ) { Dmake_normals( ); Dcalc_plane_eq( ); // norm is a unit vector setup_poly_vox( ); resize_poly_vox = 0; } if( DOCOLLIDE ) if( COLLISION_METHOD == 0 ) find_skulls( ); DRAW_STATUS( "Xfering hair" ); // ok now the old is approximately lined up with the new vid = -1; for( x = 0; x < totalverts; x++ ) { float smallest = 999991; BIG = ( float ) 999999.0f; // find 3 closest verts // find closest for( y = 0; y < oldtotalverts; y++ ) { float d; int chk = 0; // if (hair[x].mtl==matmap[oldhair[y].mtl]) // its a match // actually we don't care if( oldskull_sphere == -1 ) chk = 1; if( chk == 0 ) if( oldhair[y].mtl != oldskull_sphere ) chk = 1; if( chk == 1 ) { { int chk = 0; if( skull_sphere == -1 ) chk = 1; if( hair[x].mtl != skull_sphere ) if( skull_sphere != -1 ) chk = 1; if( chk == 1 ) // if (hair[x].mtl!=splines) // if ((oldsplines<0)||((oldsplines>=0)&&(oldhair[y].mtl!=oldsplines))) if( oldmtl != -1 ) if( oldhair[y].mtl == oldmtl ) { VERT a, b; a = hair[x].hv[0]; b = oldhair[y].hv[0]; d = Distance( a, b ); if( d < BIG ) { BIG = d; vid = y; } } // match } } } // y { // char tmp[255]; // sprintf(tmp,"%d",vid); // DRAW_STATUS(tmp); } //hair[x]=oldhair[x]; //vid=x; { int chk = 0; if( skull_sphere == -1 ) chk = 1; if( skull_sphere != -1 ) if( hair[x].mtl != skull_sphere ) chk = 1; if( chk == 1 ) if( vid >= 0 ) { if( splines < 0 ) { memcpy( &base, &hair[x], sizeof( BASEHAIR ) ); //memcpy (&restbase,&resthair[x],sizeof(BASEHAIR)); memcpy( &hair[x], &oldhair[vid], sizeof( BASEHAIR ) ); // memcpy(&resthair[x],&oldresthair[vid],sizeof(BASEHAIR)); } if( splines < 0 ) if( ( vid >= 0 ) ) for( y = 0; y < 15; y++ ) { // hair[x].hv[y]=oldhair[vid].hv[y]; hair[x].hv[y].x -= oldhair[vid].hv[0].x; hair[x].hv[y].y -= oldhair[vid].hv[0].y; hair[x].hv[y].z -= oldhair[vid].hv[0].z; hair[x].hv[y].x += base.hv[0].x; hair[x].hv[y].y += base.hv[0].y; hair[x].hv[y].z += base.hv[0].z; // hair[x].noisev[y]=oldhair[vid].noisev[y]; hair[x].noisev[y].x -= oldhair[vid].noisev[0].x; hair[x].noisev[y].y -= oldhair[vid].noisev[0].y; hair[x].noisev[y].z -= oldhair[vid].noisev[0].z; hair[x].noisev[y].x += base.noisev[0].x; hair[x].noisev[y].y += base.noisev[0].y; hair[x].noisev[y].z += base.noisev[0].z; hair[x].resthv[y] = oldhair[vid].resthv[y]; hair[x].resthv[y].x -= oldhair[vid].resthv[0].x; hair[x].resthv[y].y -= oldhair[vid].resthv[0].y; hair[x].resthv[y].z -= oldhair[vid].resthv[0].z; hair[x].resthv[y].x += base.resthv[0].x; hair[x].resthv[y].y += base.resthv[0].y; hair[x].resthv[y].z += base.resthv[0].z; hair[x].noisev[y] = oldhair[vid].noisev[y]; hair[x].noisev[y].x -= oldhair[vid].noisev[0].x; hair[x].noisev[y].y -= oldhair[vid].noisev[0].y; hair[x].noisev[y].z -= oldhair[vid].noisev[0].z; hair[x].noisev[y].x += base.noisev[0].x; hair[x].noisev[y].y += base.noisev[0].y; hair[x].noisev[y].z += base.noisev[0].z; } if( splines < 0 ) if( ( vid >= 0 ) ) //&&(vid[1]>0)&&(vid[2]>0)) { int t; hair[x].restlength = oldhair[vid].restlength; //*scalar.x+ // resthair[x].restlength=oldresthair[vid].restlength; // resthair[x]=hair[x]; // thishair[x]=hair[x]; // lasthair[x]=hair[x]; for( t = 0; t < 15; t++ ) { hair[x].resthv[t] = hair[x].hv[t]; hair[x].lasthv[t] = hair[x].hv[t]; } } } } /// if (hair[x].restlength>0) /// recalc_hair(x); } // x mkbounds( ); reset_faces( ); checkforzero( ); Nfree( oldhair ); //Nfree(oldresthair); Nfree( oldfacelist ); Nfree( oldface_start ); Nfree( oldface_end ); check_wmaps( ); // LOCAL_CNT[0]=6500; // LOCAL_CNT[1]=1500; // LOCAL_CNT[2]=500; // LOCAL_CNT[3]=100; // LOCAL_CNT[4]=1500; for( x = 0; x < 5; x++ ) LOCAL_CNT[x] = old_cnt[x]; for( x = 0; x < 5; x++ ) LOCAL_SHADCNT[x] = old_shadcnt[x]; for( x = 0; x < 5; x++ ) LOCAL_PASSES[x] = old_passes[x]; reset_faces( ); checkforzero( ); //reset_faces(); DRAW_STATUS( "Done with Xfer" ); //for (x=0;x<5;x++) if (LOCAL_CNT!=0) LOCAL_CNT[x]=old_cnt[x]; //printf ("done with xplant\n"); reset_noisespace( ); } #ifdef LIB static void draw_a_clump( RENDERHAIR * ); #endif //#ifdef NOLIB //void draw_a_clump(BASERHAIR) ; //#endif //static BASEHAIR *spare=NULL; //static BASEHAIR *spare2=NULL; typedef struct { float u, v; int pid; float scale; VERT color; VERT jitter; } STRAND; //STRAND strand[2000000]; //#include "joemath.h" //#include "vector_stuff.c" typedef struct { VERT c; float minrad; float maxrad; } SKULLTYPE; static SKULLTYPE skull; static SKULLTYPE skulls[800]; static float Distance( VERT a, VERT b ) //VERT a, b; { double dx = a.x - b.x; double dy = a.y - b.y; double dz = a.z - b.z; return ( ( float ) fsqrt( ( dx * dx ) + ( dy * dy ) + ( dz * dz ) ) ); } static VERT find_delta( VERT a, VERT b ) { VERT ret; float dx, dy, dz; dx = b.x - a.x; dy = b.y - a.y; dz = b.z - a.z; ret.x = dx; ret.y = dy; ret.z = dz; return ( ret ); } static VERT find_vector( VERT, VERT ); #include "surface_collide.c" void OLDrepulse_hair( int g ) { int x; int q, qq; SOFTGUIDE thisp, lastp; int slg = -1; { if( head >= 0 ) if( hair[g].mtl == head ) slg = 0; if( beard >= 0 ) if( hair[g].mtl == beard ) slg = 1; if( eyebrow >= 0 ) if( hair[g].mtl == eyebrow ) slg = 2; if( eyelash >= 0 ) if( hair[g].mtl == eyelash ) slg = 3; if( splines >= 0 ) if( hair[g].mtl == splines ) slg = 4; } q = g; if( slg >= 0 ) if( totalverts > 0 ) #ifndef LW3D if( COLLISION_METHOD == 0 ) #endif if( Gsurface_collide[slg] == 1 ) { if( skull_sphere >= 0 ) if( totalskulls > 0 ) { for( qq = 0; qq < totalskulls; qq++ ) { // if (hair[q].mtl==head) { VERT c; float rad; rad = skulls[qq].minrad; c = skulls[qq].c; for( x = 1; x < 15; x++ ) { VERT a, vec; float d, dx, dy, dz; a = hair[g].hv[x]; d = distance( c, a ); dx = a.x - c.x; dy = a.y - c.y; dz = a.z - c.z; d = dx * dx + dy * dy + dz * dz; rad = ( skulls[qq].maxrad + skulls[qq].minrad ) / 2.0f; rad += ( rad * .01 ); // rad+=(skulls[qq].maxrad*.3)*(float)(((x)/15.0)*.5+.5); if( d < rad * rad ) if( hair[g].restlength != 0.0 ) { vec = find_vector( c, a ); vec = Vnorm( vec ); { VERT tmpv; tmpv = hair[g].hv[x]; hair[g].hv[x].x = c.x + vec.x * rad; hair[g].hv[x].y = c.y + vec.y * rad; hair[g].hv[x].z = c.z + vec.z * rad; // hair[g].hv[x].x=hair[g].hv[x].x*.9+tmpv.x*.1; // hair[g].hv[x].y=hair[g].hv[x].y*.9+tmpv.y*.1; // hair[g].hv[x].z=hair[g].hv[x].z*.9+tmpv.z*.1; } } } } } } } } static void SOLDrepulse_hair( int g ) { int x; int q, qq; //#ifndef NOLIB //#ifndef RENDERLW //if (EXTERNAL_COLLISIONS==1) int slg = -1; q = g; { if( head >= 0 ) if( Shair[g].mtl == head ) slg = 0; if( beard >= 0 ) if( Shair[g].mtl == beard ) slg = 1; if( eyebrow >= 0 ) if( Shair[g].mtl == eyebrow ) slg = 2; if( eyelash >= 0 ) if( Shair[g].mtl == eyelash ) slg = 3; if( splines >= 0 ) if( Shair[g].mtl == splines ) slg = 4; } q = g; // if (EXTERNAL_COLLISIONS==0) if( slg >= 0 ) if( totalverts > 0 ) #ifndef LW3D if( COLLISION_METHOD == 0 ) #endif if( Gsurface_collide[slg] == 1 ) if( splines >= 0 ) if( skull_sphere >= 0 ) if( totalskulls > 0 ) { for( qq = 0; qq < totalskulls; qq++ ) { { VERT c; float rad; rad = skulls[qq].minrad; c = skulls[qq].c; for( x = 1; x < 15; x++ ) { VERT a, vec; float d, dx, dy, dz; a = Shair[g].hv[x]; d = distance( c, a ); dx = a.x - c.x; dy = a.y - c.y; dz = a.z - c.z; d = dx * dx + dy * dy + dz * dz; rad = ( skulls[qq].maxrad + skulls[qq].minrad ) / 2.0f; /// rad+=(rad*.25); rad += ( skulls[qq].maxrad * .3 ) * ( float ) ( ( ( x ) / 15.0 ) * .5 + .5 ); if( d < rad * rad ) if( Shair[g].restlength != 0.0 ) { vec = find_vector( c, a ); vec = Vnorm( vec ); Shair[g].hv[x].x = c.x + vec.x * rad; Shair[g].hv[x].y = c.y + vec.y * rad; Shair[g].hv[x].z = c.z + vec.z * rad; } } } } } } static void repulse_hair( int g ) { int x; int mt; int slg = -1; mt = hair[g].mtl; if( head >= 0 ) if( mt == head ) slg = 0; if( beard >= 0 ) if( mt == beard ) slg = 1; if( eyebrow >= 0 ) if( mt == eyebrow ) slg = 2; if( eyelash >= 0 ) if( mt == eyelash ) slg = 3; if( splines >= 0 ) if( mt == splines ) slg = 4; if( slg >= 0 ) hair[g].slgroup = slg; //printf ("hair[%d].slgroup = %d\n",g,slg); if( DOCOLLIDE ) // surface_collide(g); if( COLLISION_METHOD == 1 ) if( Gsurface_collide[slg] == 1 ) if( hair[g].restlength > 0 ) { //printf ("collision_method = %d ",COLLISION_METHOD); //for (x=0;x<5;x++) printf ("%d ",Gsurface_collide[x]); //printf ("\n"); surface_collide( g, ( float ) restBOUNDLENGTH / 4.0 ); } //#ifndef DOCOLLIDE if( COLLISION_METHOD == 0 ) if( Gsurface_collide[hair[g].mtl] == 1 ) if( hair[g].restlength > 0 ) { //DRAW_STATUS("spherical"); OLDrepulse_hair( g ); } //#endif #ifdef EXTERNAL_COLLISION if( COLLISION_METHOD == 2 ) { //#ifndef NOLIB //#ifndef RENDERLW //#ifdef SOFTIMAGE int x; VERT vector; SOFTGUIDE thisp, lastp; VERT thispos, lastpos; //printf ("restlength= %f\n",hair[g].restlength); if( hair[g].restlength > 0.0 ) for( x = 0; x < 15; x++ ) { thispos = hair[g].hv[x]; lastpos = hair[g].lasthv[x]; //printf ("hello\n"); // convert to world (already done) thispos.x *= restBOUNDLENGTH; thispos.y *= restBOUNDLENGTH; thispos.z *= restBOUNDLENGTH; lastpos.x *= restBOUNDLENGTH; lastpos.y *= restBOUNDLENGTH; lastpos.z *= restBOUNDLENGTH; thisp.guide[x] = thispos; lastp.guide[x] = lastpos; thisp.select[x] = hair[g].select[x]; thisp.lock[x] = hair[g].pfID[x]; thisp.vid = hair[g].vid; lastp.select[x] = hair[g].select[x]; lastp.lock[x] = hair[g].pfID[x]; //vector.x=thispos.x-lastpos.x; //vector.y=thispos.y-lastpos.y; //vector.z=thispos.z-lastpos.z; { // int lockflag; //lockflag=hair[g].pfID[x]; //if (lockflag>=0) lockflag=1; //if (lockflag<0) lockflag=0; //MAYAexternal_collision(&lastpos,&vector); } } if( hair[g].restlength > 0.0 ) { float seglen; seglen = hair[g].restlength * restBOUNDLENGTH; for( x = 0; x < 15; x++ ) { lastp.guide[x].z *= -1.0f; thisp.guide[x].z *= -1.0f; lastp.velocity[x].z *= -1.0f; thisp.velocity[x].z *= -1.0f; } lastp.norm.z *= -1.0f; thisp.norm.z *= -1.0f; MAYAexternal_collision( &lastp, &thisp, seglen ); for( x = 0; x < 15; x++ ) { lastp.guide[x].z *= -1.0f; thisp.guide[x].z *= -1.0f; lastp.velocity[x].z *= -1.0f; thisp.velocity[x].z *= -1.0f; } lastp.norm.z *= -1.0f; thisp.norm.z *= -1.0f; } if( hair[g].restlength > 0.0 ) for( x = 1; x < 15; x++ ) { thisp.guide[x].x /= restBOUNDLENGTH; thisp.guide[x].y /= restBOUNDLENGTH; thisp.guide[x].z /= restBOUNDLENGTH; hair[g].hv[x] = thisp.guide[x]; } } #endif } static void Srepulse_hair9( int g ) { } static void Srepulse_hair( int g ) { int mt; int slg = -1; mt = Shair[g].mtl; if( head >= 0 ) if( mt == head ) slg = 0; if( beard >= 0 ) if( mt == beard ) slg = 1; if( eyebrow >= 0 ) if( mt == eyebrow ) slg = 2; if( eyelash >= 0 ) if( mt == eyelash ) slg = 3; if( splines >= 0 ) if( mt == splines ) slg = 4; if( slg >= 0 ) Shair[g].slgroup = slg; #ifdef EXTERNAL_COLLISION if( COLLISION_METHOD == 2 ) { //#ifndef NOLIB //#ifndef RENDERLW //#ifdef SOFTIMAGE int x; VERT vector; SOFTGUIDE thisp, lastp; VERT thispos, lastpos; //printf ("restlength= %f\n",hair[g].restlength); if( Shair[g].restlength > 0.0 ) for( x = 0; x < 15; x++ ) { thispos = Shair[g].hv[x]; lastpos = Slasthair[g].hv[x]; //printf ("hello\n"); // convert to world (already done) thispos.x *= restBOUNDLENGTH; thispos.y *= restBOUNDLENGTH; thispos.z *= restBOUNDLENGTH; lastpos.x *= restBOUNDLENGTH; lastpos.y *= restBOUNDLENGTH; lastpos.z *= restBOUNDLENGTH; thisp.guide[x] = thispos; lastp.guide[x] = lastpos; thisp.select[x] = Shair[g].select[x]; thisp.lock[x] = Shair[g].pfID[x]; thisp.vid = Shair[g].vid; lastp.select[x] = Shair[g].select[x]; lastp.lock[x] = Shair[g].pfID[x]; //vector.x=thispos.x-lastpos.x; //vector.y=thispos.y-lastpos.y; //vector.z=thispos.z-lastpos.z; { // int lockflag; //lockflag=hair[g].pfID[x]; //if (lockflag>=0) lockflag=1; //if (lockflag<0) lockflag=0; //MAYAexternal_collision(&lastpos,&vector); } } if( Shair[g].restlength > 0.0 ) { float seglen; seglen = hair[g].restlength * restBOUNDLENGTH; for( x = 0; x < 15; x++ ) { lastp.guide[x].z *= -1.0f; thisp.guide[x].z *= -1.0f; lastp.velocity[x].z *= -1.0f; thisp.velocity[x].z *= -1.0f; } lastp.norm.z *= -1.0f; thisp.norm.z *= -1.0f; MAYAexternal_collision( &lastp, &thisp, seglen ); for( x = 0; x < 15; x++ ) { lastp.guide[x].z *= -1.0f; thisp.guide[x].z *= -1.0f; lastp.velocity[x].z *= -1.0f; thisp.velocity[x].z *= -1.0f; } lastp.norm.z *= -1.0f; thisp.norm.z *= -1.0f; } if( Shair[g].restlength > 0.0 ) for( x = 1; x < 15; x++ ) { thisp.guide[x].x /= restBOUNDLENGTH; thisp.guide[x].y /= restBOUNDLENGTH; thisp.guide[x].z /= restBOUNDLENGTH; Shair[g].hv[x] = thisp.guide[x]; } } #endif if( COLLISION_METHOD == 1 ) if( DOCOLLIDE ) { // surface_collide(g); if( Shair[g].restlength > 0 ) { Ssurface_collide( g, ( float ) restBOUNDLENGTH / 4.0 ); } } if( COLLISION_METHOD == 0 ) SOLDrepulse_hair( g ); } static int friction( int g, int x ) { int q; int ret = 0; q = g; if( 0 == 1 ) if( hair[q].mtl == head ) { VERT c; float rad; rad = skull.maxrad; c = skull.c; // for (x=2;x<15;x++) { VERT a, vec; float d; a = hair[g].hv[x]; a.x += hair[g].velocity[x].x; a.y += hair[g].velocity[x].y; a.z += hair[g].velocity[x].z; vec = find_vector( c, a ); d = distance( c, a ); rad += ( hair[g].restlength / 50.0 ) * ( float ) ( 15 - x ); if( d < rad ) { ret = 1; } } } return ( ret ); } static void recalc_hair( int g ) { int xx; // recalc_hair_lores(g); // recalc_hair_lores(g); // recalc_hair2(g); // recalc_hair2( g ); //// recalc_hair2(g); int y, x = 0; float qq = 0; x = g; if( hair[x].restlength > .0001f ) { for( y = 1; y < 15; y++ ) qq += hair[x].w[y]; { qq = hair[x].select[0]; } if( hair[x].restlength == 0.0f ) qq = 0; if( scale_stat ) qq = hair[x].select[0]; Gcollision_hit = 0; // if( !scale_stat ) if( qq > 0 ) recalc_hair2( x ); if( Gcollision_hit == 1 ) { int xx, y; for( xx = 0; xx < 15; xx++ ) hair[x].sparehv[xx] = hair[x].hv[xx]; } // if( !scale_stat ) if( DOCOLLIDE ) if( Gcollision_hit == 1 ) for( xx = 0; xx < 12; xx++ ) if( qq > 0 ) if( Gcollision_hit == 1 ) { Gcollision_hit = 0; recalc_hair2( x ); if( Gcollision_hit == 1 ) { int xx, y; for( xx = 0; xx < 15; xx++ ) hair[x].sparehv[xx] = hair[x].hv[xx]; } } } for( xx = 0; xx < totalverts; xx++ ) if( hair[xx].restlength < .0001f ) { int y; for( y = 0; y < 15; y++ ) hair[xx].hv[y] = v[xx]; } } static void recalc_hair2( int g ) { int x; float r1; float stiff3; r1 = hair[g].restlength; if( head >= 0 ) if( hair[g].mtl == head ) stiff3 = sliders[8][0].value; if( beard >= 0 ) if( hair[g].mtl == beard ) stiff3 = sliders[8][1].value; if( eyebrow >= 0 ) if( hair[g].mtl == eyelash ) stiff3 = sliders[8][2].value; if( eyelash >= 0 ) if( hair[g].mtl == eyebrow ) stiff3 = sliders[8][3].value; if( splines >= 0 ) if( hair[g].mtl == splines ) stiff3 = sliders[8][4].value; //for (it=0;it<5;it++) if( r1 > 0.0001f ) { // if (stiff3<.97) //repulse_hair(g); DOCOLLIDE = 0; if( Gsurface_collide[0] == 1 ) DOCOLLIDE = 1; if( skull_sphere == -1 ) DOCOLLIDE = 0; restore_locked_hair( g ); if( DOCOLLIDE ) { if( selmode != VERTS ) for( x = ( 15 - 2 ); x > 0; x-- ) // recalc from end first if( hair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = hair[g].hv[x]; b = hair[g].hv[x + 1]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; if( selmode != VERTS ) hair[g].hv[x] = a; if( ( selmode == VERTS ) && ( hair[g].select[x] == 0 ) ) { hair[g].hv[x] = a; } } restore_locked_hair( g ); repulse_hair( g ); for( x = 0; x < ( 15 - 1 ); x++ ) // recalc from root now if( hair[g].pfID[x + 1] == -1 ) { VERT vec; VERT a, b, c; a = hair[g].hv[x]; b = hair[g].hv[x + 1]; vec = find_vector( a, b ); c.x = hair[g].hv[x].x + ( vec.x * r1 ); c.y = hair[g].hv[x].y + ( vec.y * r1 ); c.z = hair[g].hv[x].z + ( vec.z * r1 ); if( selmode != VERTS ) hair[g].hv[x + 1] = c; if( ( selmode == VERTS ) && ( hair[g].select[x + 1] == 0 ) ) { hair[g].hv[x + 1] = c; } } } restore_locked_hair( g ); // repulse_hair(g); // if it's VERTS do it again //if (selmode!=VERTS) for( x = ( 15 - 2 ); x > 0; x-- ) // recalc from end first if( hair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = hair[g].hv[x]; b = hair[g].hv[x + 1]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; hair[g].hv[x] = a; } // if (stiff3<.97) // repulse_hair(g); // if (selmode==VERTS) for( x = 0; x < ( 15 - 1 ); x++ ) // recalc from root now if( hair[g].pfID[x + 1] == -1 ) { VERT vec; VERT a, b, c; a = hair[g].hv[x]; b = hair[g].hv[x + 1]; vec = find_vector( a, b ); c.x = a.x + ( vec.x * r1 ); c.y = a.y + ( vec.y * r1 ); c.z = a.z + ( vec.z * r1 ); hair[g].hv[x + 1] = c; } restore_locked_hair( g ); if( DOCOLLIDE ) repulse_hair( g ); } { int xx; for( xx = 0; xx < totalverts; xx++ ) if( hair[xx].restlength < .0001f ) { int y; for( y = 0; y < 15; y++ ) hair[xx].hv[y] = v[xx]; } } } static void recalc_hair_lores( int g ) { int x; float r1; float stiff3; r1 = hair[g].restlength * 3.0f; if( head >= 0 ) if( hair[g].mtl == head ) stiff3 = sliders[8][0].value; if( beard >= 0 ) if( hair[g].mtl == beard ) stiff3 = sliders[8][1].value; if( eyebrow >= 0 ) if( hair[g].mtl == eyelash ) stiff3 = sliders[8][2].value; if( eyelash >= 0 ) if( hair[g].mtl == eyebrow ) stiff3 = sliders[8][3].value; if( splines >= 0 ) if( hair[g].mtl == splines ) stiff3 = sliders[8][4].value; //for (it=0;it<5;it++) if( r1 > 0 ) { //if (global_lores) spline_chain(g); // if (stiff3<.97) //repulse_hair(g); restore_locked_hair( g ); if( selmode != VERTS ) for( x = ( 15 - 1 - 3 ); x > 0; x -= 3 ) // recalc from end first if( hair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = hair[g].hv[x]; b = hair[g].hv[x + 3]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; if( selmode != VERTS ) hair[g].hv[x] = a; if( ( selmode == VERTS ) && ( hair[g].select[x] == 0 ) ) { hair[g].hv[x] = a; } } restore_locked_hair( g ); repulse_hair( g ); for( x = 0; x < 1; x += 3 ) // recalc from root now if( hair[g].pfID[x + 2] == -1 ) { VERT vec; VERT a, b, c; a = hair[g].hv[x]; b = hair[g].hv[x + 2]; vec = find_vector( a, b ); c.x = hair[g].hv[x].x + ( vec.x * r1 * ( 2.0 / 3.0 ) ); c.y = hair[g].hv[x].y + ( vec.y * r1 * ( 2.0 / 3.0 ) ); c.z = hair[g].hv[x].z + ( vec.z * r1 * ( 2.0 / 3.0 ) ); if( selmode != VERTS ) hair[g].hv[x + 2] = c; if( ( selmode == VERTS ) && ( hair[g].select[x + 3] == 0 ) ) { hair[g].hv[x + 2] = c; } } restore_locked_hair( g ); for( x = 2; x <= ( 15 - 1 - 3 ); x += 3 ) // recalc from root now if( hair[g].pfID[x + 3] == -1 ) { VERT vec; VERT a, b, c; a = hair[g].hv[x]; b = hair[g].hv[x + 3]; vec = find_vector( a, b ); c.x = hair[g].hv[x].x + ( vec.x * r1 ); c.y = hair[g].hv[x].y + ( vec.y * r1 ); c.z = hair[g].hv[x].z + ( vec.z * r1 ); if( selmode != VERTS ) hair[g].hv[x + 3] = c; if( ( selmode == VERTS ) && ( hair[g].select[x + 3] == 0 ) ) { hair[g].hv[x + 3] = c; } } restore_locked_hair( g ); // repulse_hair(g); // if it's VERTS do it again //if (selmode!=VERTS) for( x = ( 15 - 1 - 3 ); x > 0; x -= 3 ) // recalc from end first if( hair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = hair[g].hv[x]; b = hair[g].hv[x + 3]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; hair[g].hv[x] = a; } // if (stiff3<.97) // repulse_hair(g); // if (selmode==VERTS) for( x = 2; x < ( 15 - 1 - 3 ); x += 3 ) // recalc from root now if( hair[g].pfID[x + 3] == -1 ) { VERT vec; VERT a, b, c; a = hair[g].hv[x]; b = hair[g].hv[x + 3]; vec = find_vector( a, b ); c.x = hair[g].hv[x].x + ( vec.x * r1 ); c.y = hair[g].hv[x].y + ( vec.y * r1 ); c.z = hair[g].hv[x].z + ( vec.z * r1 ); hair[g].hv[x + 3] = c; } restore_locked_hair( g ); // repulse_hair(g); if( global_lores ) spline_chain( g ); } } static void dyn_recalc_hair2( int g ) { int ii, x; float r1; r1 = hair[g].restlength; #ifdef LIB for( ii = 0; ii < 1; ii++ ) { #endif // if (0==1) // repulse_hair(g); restore_locked_hair( g ); if( r1 > 0.0001f ) { if( 0 == 1 ) for( x = ( 15 - 2 ); x > 0; x-- ) // recalc from end first if( hair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = hair[g].hv[x]; b = hair[g].hv[x + 1]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; hair[g].hv[x] = a; } //#endif ///// july repulse_hair(g); restore_locked_hair( g ); for( x = 0; x < ( 15 - 1 ); x++ ) // recalc from root now if( hair[g].pfID[x + 1] == -1 ) { VERT vec; VERT a, b, c; a = hair[g].hv[x]; b = hair[g].hv[x + 1]; vec = find_vector( a, b ); c.x = hair[g].hv[x].x + ( vec.x * r1 ); c.y = hair[g].hv[x].y + ( vec.y * r1 ); c.z = hair[g].hv[x].z + ( vec.z * r1 ); //if (selmode!=VERTS) hair[g].hv[x + 1] = c; //repulse_hair(g); } for( x = ( 15 - 2 ); x > 0; x-- ) // recalc from end first if( hair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = hair[g].hv[x]; b = hair[g].hv[x + 1]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; hair[g].hv[x] = a; } restore_locked_hair( g ); #ifdef LIB } #endif repulse_hair( g ); } } static void dyn_recalc_hair( int g ) { dyn_recalc_hair2( g ); } static void Sdyn_recalc_hair( int g ) { int ii, x; float r1; r1 = Shair[g].restlength; //#ifdef hmm #ifdef LIB for( ii = 0; ii < 1; ii++ ) { #endif Srestore_locked_hair( g ); if( r1 > 0.0001f ) { //if (0==1) //#endif // Srepulse_hair(g); Srestore_locked_hair( g ); for( x = 0; x < ( 15 - 1 ); x++ ) // recalc from root now if( Sresthair[g].pfID[x + 1] == -1 ) { VERT vec; VERT a, b, c; a = Shair[g].hv[x]; b = Shair[g].hv[x + 1]; vec = find_vector( a, b ); c.x = Shair[g].hv[x].x + ( vec.x * r1 ); c.y = Shair[g].hv[x].y + ( vec.y * r1 ); c.z = Shair[g].hv[x].z + ( vec.z * r1 ); //if (selmode!=VERTS) Shair[g].hv[x + 1] = c; //repulse_hair(g); } for( x = ( 15 - 2 ); x > 0; x-- ) // recalc from end first if( Sresthair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = Shair[g].hv[x]; b = Shair[g].hv[x + 1]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; Shair[g].hv[x] = a; } Srestore_locked_hair( g ); #ifdef LIB } #endif Srepulse_hair( g ); } } static void blow_hair( float wx, float wy, float wz ) { int x, it; for( it = 0; it < 15; it++ ) { for( x = 0; x < totalverts; x++ ) { // if (hair[x].mtl==head) { int qq; for( qq = 1; qq < 8; qq++ ) { hair[x].hv[qq].x = v[x].x + vn[x].x * hair[x].restlength * qq; hair[x].hv[qq].y = v[x].y + vn[x].y * hair[x].restlength * qq; hair[x].hv[qq].z = v[x].z + vn[x].z * hair[x].restlength * qq; } hair[x].hv[14].y -= hair[x].restlength * 1.0f; if( it < 5 ) hair[x].hv[14].z += hair[x].restlength * 15.0f; recalc_hair( x ); // repulse_hair(x); // recalc_hair(x); } } } } static int chkf2( int f ) { int t = 0; int x; for( x = Dface_start[f]; x < Dface_end[f]; x++ ) { if( Dtag[Dfacelist[x]] < 0 ) t++; } if( t > 0 ) t = 1; return ( t ); } static int tagnext( int tt ) { int x; int y, quit = 0; int gotone = 0; if( skull_sphere != -1 ) for( x = 0; x < Dtotalfaces; x++ ) { if( quit == 0 ) if( Dmtlgroup[x] == skull_sphere ) if( chkf2( x ) ) { for( y = Dface_start[x]; y < Dface_end[x]; y++ ) { Dtag[Dfacelist[y]] = tt; } gotone = 1; quit = 1; } } return ( gotone ); } static int chkf( int f, int tt ) { int t = 0; int x; if( skull_sphere >= 0 ) if( Dmtlgroup[f] == skull_sphere ) { int ct = 0; for( x = Dface_start[f]; x < Dface_end[f]; x++ ) { if( Dtag[Dfacelist[x]] == tt ) t++; ct++; } if( t == ct ) t = 0; } return ( t ); } static int tagconn( int tt ) { int ret = 0; int x, y; int tg = 0; for( x = 0; x < Dtotalfaces; x++ ) { if( chkf( x, tt ) > 0 ) { for( y = Dface_start[x]; y < Dface_end[x]; y++ ) { Dtag[Dfacelist[y]] = tt; } ret = 1; tg++; } } return ( ret ); } static int tagconnect( int tt ) { int quit = 1; while( quit == 1 ) { quit = tagconn( tt ); } return ( quit ); } static void mktags( void ) { int x; int nomore = 0; int quit = 1; for( x = 0; x < Dtotalverts; x++ ) Dtag[x] = -1; totalskulls = 0; if( head >= 0 ) if( skull_sphere >= 0 ) while( quit != 0 ) { nomore = tagnext( totalskulls ); if( nomore != 0 ) tagconnect( totalskulls ); if( nomore != 0 ) totalskulls++; quit = nomore; } } static SKULLTYPE find_skull( void ) { int x, th = 0; SKULLTYPE ret; ret.c.x = 0; ret.c.y = 0; ret.c.z = 0; if( skull_sphere != -1 ) { for( x = 0; x < Dtotalverts; x++ ) { if( Dvertgroup[x] == skull_sphere ) { ret.c.x += Dv[x].x; ret.c.y += Dv[x].y; ret.c.z += Dv[x].z; th++; } } if( th != 0 ) { ret.c.x /= ( float ) th; ret.c.y /= ( float ) th; ret.c.z /= ( float ) th; } // find minrad maxrad ret.minrad = ( float ) 999999999; ret.maxrad = 0; for( x = 0; x < Dtotalverts; x++ ) { if( Dvertgroup[x] == skull_sphere ) { float d; float dx, dy, dz; dx = Dv[x].x - ret.c.x; dy = Dv[x].y - ret.c.y; dz = Dv[x].z - ret.c.z; d = fsqrt( dx * dx + dy * dy + dz * dz ); if( d < ret.minrad ) ret.minrad = d; if( d > ret.maxrad ) ret.maxrad = d; } } // { // FILE *fp; // fp=fopen("skull.dat","w"); // fprintf (fp,"center %f %f %f rad %f",ret.c.x,ret.c.y,ret.c.z,ret.minrad); // fclose(fp); // } } return ( ret ); } static void find_skulls( void ) { int x, th = 0; SKULLTYPE ret; int qqq; ret.c.x = 0; ret.c.y = 0; ret.c.z = 0; #ifndef LW3D if( COLLISION_METHOD == 0 ) #endif // if( totalskulls == 0 ) <- we took this out { totalskulls = 0; // reset_hair(); if( skull_sphere >= 0 ) mktags( ); // if (head>=0) if( skull_sphere >= 0 ) for( qqq = 0; qqq < totalskulls; qqq++ ) { ret.c.x = 0; ret.c.y = 0; ret.c.z = 0; th = 0; if( skull_sphere != -1 ) { for( x = 0; x < Dtotalverts; x++ ) { if( Dtag[x] == qqq ) { // ret.c.x += Dv[vlink[x]].x; // ret.c.y += Dv[vlink[x]].y; // ret.c.z += Dv[vlink[x]].z; ret.c.x += Dv[x].x; ret.c.y += Dv[x].y; ret.c.z += Dv[x].z; th++; } } if( th != 0 ) { ret.c.x /= ( float ) th; ret.c.y /= ( float ) th; ret.c.z /= ( float ) th; } // find minrad maxrad ret.minrad = ( float ) 999999999; ret.maxrad = 0; for( x = 0; x < Dtotalverts; x++ ) { if( Dtag[x] == qqq ) { float d; float dx, dy, dz; dx = Dv[x].x - ret.c.x; dy = Dv[x].y - ret.c.y; dz = Dv[x].z - ret.c.z; // dx = Dv[vlink[x]].x - ret.c.x; // dy = Dv[vlink[x]].y - ret.c.y; // dz = Dv[vlink[x]].z - ret.c.z; d = fsqrt( dx * dx + dy * dy + dz * dz ); if( d < ret.minrad ) ret.minrad = d; if( d > ret.maxrad ) ret.maxrad = d; } } } skulls[qqq] = ret; } // reset proper tags for( x = 0; x < Dtotalverts; x++ ) Dtag[x]=0; for( x = 0; x < totalverts; x++ ) { Dtag[vlink[x]] = 1; } // return(ret); // { // FILE *fp; // fp=fopen("zzz.txt","w"); // fprintf (fp,"Located %d collision spheres\n",totalskulls); // fclose(fp); //} } } static void sproing( int q ) { int x; int g; VERT vnn; g = q; if( splines < 0 ) { vnn = vn[g]; vnn.z += .00001; vnn = Vnorm( vnn ); if( total_splines == 0 ) for( x = 0; x < 15; x++ ) { float rl; int t; rl = hair[g].restlength; hair[g].hv[x].x = v[g].x + ( vnn.x * rl * ( float ) x ); hair[g].hv[x].y = v[g].y + ( vnn.y * rl * ( float ) x ); hair[g].hv[x].z = v[g].z + ( vnn.z * rl * ( float ) x ); hair[g].norm = vn[g]; // hair[g].uu = ucord[g]; // hair[g].vv = vcord[g]; for( t = 0; t < 15; t++ ) { hair[g].resthv[t] = hair[g].hv[t]; } } } if( total_splines != 0 ) { vnn = Shair[g].norm; vnn.z += .00001; vnn = Vnorm( vnn ); for( x = 0; x < 15; x++ ) { float rl; int t; rl = Shair[g].restlength; Shair[g].hv[x].x = Shair[g].hv[0].x + ( vnn.x * rl * ( float ) x ); Shair[g].hv[x].y = Shair[g].hv[0].y + ( vnn.y * rl * ( float ) x ); Shair[g].hv[x].z = Shair[g].hv[0].z + ( vnn.z * rl * ( float ) x ); // hair[g].uu = ucord[g]; // hair[g].vv = vcord[g]; for( t = 0; t < 15; t++ ) { Shair[g].resthv[t] = Shair[g].hv[t]; } } } } static void sproing2( void ) { int x; int y; // for( x = 0; x < totalverts; x++ ) // for( y = 0; y < 15; y++ ) // hair[x].select[y] = 0; if( total_splines == 0 ) for( x = 0; x < totalverts; x++ ) if( ( hair[x].mtl == head ) || ( hair[x].mtl == beard ) || ( hair[x].mtl == eyelash ) || ( hair[x].mtl == eyebrow ) ) if( hair[x].restlength < .01f ) { // hair[x].select[14] = 1; // hair[x].select[0] = 1; hair[x].restlength = ( float ) ( BOUNDLENGTH ) / 110.0f; sproing( x ); } if( total_splines != 0 ) for( x = 0; x < total_splines; x++ ) if( Shair[x].restlength < .01f ) { // hair[x].select[14] = 1; // hair[x].select[0] = 1; Shair[x].restlength = ( float ) ( restBOUNDLENGTH ) / 90.0f; Sresthair[x].restlength = ( float ) ( restBOUNDLENGTH ) / 90.0f; sproing( x ); } reset_noisespace( ); } static void MS_sproing( float sz ) { int x; int y; if( splines < 0 ) for( x = 0; x < totalverts; x++ ) if( ( hair[x].mtl == head ) || ( hair[x].mtl == beard ) || ( hair[x].mtl == eyelash ) || ( hair[x].mtl == eyebrow ) ) // if (hair[x].restlength==0) if( hair[x].select[0] || hair[x].select[14] ) { hair[x].restlength = ( float ) ( ( ( float ) ( BOUNDLENGTH ) / 890.0 ) * sz ); sproing( x ); } if( splines >= 0 ) for( x = 0; x < total_splines; x++ ) if( Shair[x].select[0] || hair[x].select[14] ) { Shair[x].restlength = ( float ) ( ( ( float ) ( BOUNDLENGTH ) / 90.0 ) * sz ); sproing( x ); } reset_noisespace( ); } static void sproing3( void ) { int x; for( x = 0; x < totalverts; x++ ) // if ( // (hair[x].mtl==beard)|| // (hair[x].mtl==eyelash)|| // (hair[x].mtl==eyebrow) // ) // if (hair[x].restlength==0) { // hair[x].restlength=(float)(BOUNDLENGTH)/90.0f; sproing( x ); } } static int checkface( int i ) { int x; int ret = 0; double dr; int tr = 0; int slg = -1; if( ( i >= 0 ) && ( i < totalfaces ) ) if( poly_weight[i] != 0 ) { //if (head>=0) // if (mtlgroup[i]==head) slg=0; //if (beard>=0) // if (mtlgroup[i]==beard) slg=1; //if (eyebrow>=0) // if (mtlgroup[i]==eyebrow) slg=2; //if (eyelash>=0) // if (mtlgroup[i]==eyelash) slg=3; //if (splines>=0) // if (mtlgroup[i]==splines) slg=4; ret = 0; //if (i>=0) // if (slg>=0) { int qq; // for (qq=0;qq<(int)((float)drand98()*15.);qq++) dr=(float)drand98(); // dr=(float)drand98(); // printf ("poly_weight[i] = %f\n",poly_weight[i]); // dr*dr= 0 ) && ( i < totalfaces ) ) if( poly_weight[i] != 0 ) { //if (head>=0) // if (mtlgroup[i]==head) slg=0; //if (beard>=0) // if (mtlgroup[i]==beard) slg=1; //if (eyebrow>=0) // if (mtlgroup[i]==eyebrow) slg=2; //if (eyelash>=0) // if (mtlgroup[i]==eyelash) slg=3; //if (splines>=0) // if (mtlgroup[i]==splines) slg=4; ret = 0; //if (i>=0) // if (slg>=0) { int qq; // for (qq=0;qq<(int)((float)drand98()*15.);qq++) dr=(float)drand98(); // dr=(float)drand98(); // printf ("poly_weight[i] = %f\n",poly_weight[i]); // dr*drdensity_correct==0) ret=1; return ( ret ); } //#ifdef LIB #include "render.c" //#endif static void smooth_hair( RENDERHAIR * h, int ee ) { int x; int c1, c2, c3; VERT zr; RENDERHAIR tmpp; int hitme[130]; zr.x = 0; zr.y = 0; zr.z = 0; for( x = 0; x < ee; x++ ) { tmpp.hv[x] = h->hv[x]; tmpp.color[x] = h->color[x]; tmpp.velocity[x] = h->velocity[x]; } for( x = 0; x < 130; x++ ) { hitme[x] = 1; // tmpp.hv[x]=zr; // tmpp.color[x]=zr; } for( x = 0; x < ee; x++ ) { c1 = x - 1; if( c1 < 0 ) c1 = 0; c2 = x; c3 = x + 1; if( c3 > ee - 1 ) c3 = ee - 1; hitme[c1]++; hitme[c2]++; hitme[c3]++; tmpp.hv[c1].x += h->hv[c2].x; tmpp.hv[c1].y += h->hv[c2].y; tmpp.hv[c1].z += h->hv[c2].z; tmpp.hv[c2].x += h->hv[c2].x; tmpp.hv[c2].y += h->hv[c2].y; tmpp.hv[c2].z += h->hv[c2].z; tmpp.hv[c3].x += h->hv[c2].x; tmpp.hv[c3].y += h->hv[c2].y; tmpp.hv[c3].z += h->hv[c2].z; tmpp.color[c1].x += h->color[c2].x; tmpp.color[c1].y += h->color[c2].y; tmpp.color[c1].z += h->color[c2].z; tmpp.color[c2].x += h->color[c2].x; tmpp.color[c2].y += h->color[c2].y; tmpp.color[c2].z += h->color[c2].z; tmpp.color[c3].x += h->color[c2].x; tmpp.color[c3].y += h->color[c2].y; tmpp.color[c3].z += h->color[c2].z; tmpp.velocity[c1].x += h->velocity[c2].x; tmpp.velocity[c1].y += h->velocity[c2].y; tmpp.velocity[c1].z += h->velocity[c2].z; tmpp.velocity[c2].x += h->velocity[c2].x; tmpp.velocity[c2].y += h->velocity[c2].y; tmpp.velocity[c2].z += h->velocity[c2].z; tmpp.velocity[c3].x += h->velocity[c2].x; tmpp.velocity[c3].y += h->velocity[c2].y; tmpp.velocity[c3].z += h->velocity[c2].z; } for( x = 0; x < ee; x++ ) { tmpp.hv[x].x = tmpp.hv[x].x / ( float ) hitme[x]; tmpp.hv[x].y = tmpp.hv[x].y / ( float ) hitme[x]; tmpp.hv[x].z = tmpp.hv[x].z / ( float ) hitme[x]; tmpp.color[x].x = tmpp.color[x].x / ( float ) hitme[x]; tmpp.color[x].y = tmpp.color[x].y / ( float ) hitme[x]; tmpp.color[x].z = tmpp.color[x].z / ( float ) hitme[x]; tmpp.velocity[x].x = tmpp.velocity[x].x / ( float ) hitme[x]; tmpp.velocity[x].y = tmpp.velocity[x].y / ( float ) hitme[x]; tmpp.velocity[x].z = tmpp.velocity[x].z / ( float ) hitme[x]; h->hv[x] = tmpp.hv[x]; h->color[x] = tmpp.color[x]; h->velocity[x] = tmpp.velocity[x]; } // return(tmpp); } static void resample( BASEHAIR h, RENDERHAIR * ret ) { RENDERHAIR tmp, tmp1; int x; VERT zero; zero = h.hv[0]; //global_segs=56; tmp.segs = global_segs; //color_a_hair(&h); //// this was commented out tmp.mtl = h.mtl; tmp.uu = h.uu; tmp.vv = h.vv; tmp.cutlength = h.cutlength; tmp.thickness = h.thickness; tmp.thicknesstip = h.thicknesstip; tmp.kink = h.kink; tmp.diffuse = h.diffuse; tmp.ambient = h.ambient; tmp.dreadcount = h.dreadcount; tmp.dreadtip = h.dreadtip; tmp.dreadroot = h.dreadroot; tmp.spec = h.spec; tmp.kspec = h.kspec; tmp.restlength = h.restlength; tmp.norm = h.norm; tmp.slgroup = h.slgroup; if( tmp.segs > 5 ) { for( x = 0; x < 15; x++ ) { int x2; int xx; x2 = x * 2; tmp.hv[x2] = h.hv[x]; tmp.color[x2] = h.color[x]; tmp.velocity[x2] = h.velocity[x]; xx = x + 1; if( xx > 15 - 1 ) xx = 15 - 1; tmp.hv[x2 + 1].x = ( h.hv[x].x + h.hv[xx].x ) / 2.0f; tmp.hv[x2 + 1].y = ( h.hv[x].y + h.hv[xx].y ) / 2.0f; tmp.hv[x2 + 1].z = ( h.hv[x].z + h.hv[xx].z ) / 2.0f; tmp.color[x2 + 1].x = ( h.color[x].x + h.color[xx].x ) / 2.0f; tmp.color[x2 + 1].y = ( h.color[x].y + h.color[xx].y ) / 2.0f; tmp.color[x2 + 1].z = ( h.color[x].z + h.color[xx].z ) / 2.0f; tmp.velocity[x2 + 1].x = ( h.velocity[x].x + h.velocity[xx].x ) / 2.0f; tmp.velocity[x2 + 1].y = ( h.velocity[x].y + h.velocity[xx].y ) / 2.0f; tmp.velocity[x2 + 1].z = ( h.velocity[x].z + h.velocity[xx].z ) / 2.0f; } tmp.hv[15 * 2] = h.hv[14]; tmp.color[15 * 2] = h.color[14]; tmp.velocity[15 * 2] = h.velocity[14]; smooth_hair( &tmp, 30 ); memcpy( &tmp1, &tmp, sizeof( RENDERHAIR ) ); for( x = 0; x < 30; x++ ) { int x2; int xx; x2 = x * 2; xx = x + 1; if( xx > 30 - 1 ) xx = 30 - 1; tmp1.color[x2] = tmp.color[x]; tmp1.hv[x2] = tmp.hv[x]; tmp1.velocity[x2] = tmp.velocity[x]; tmp1.hv[x2 + 1].x = ( tmp.hv[x].x + tmp.hv[xx].x ) / 2.0f; tmp1.hv[x2 + 1].y = ( tmp.hv[x].y + tmp.hv[xx].y ) / 2.0f; tmp1.hv[x2 + 1].z = ( tmp.hv[x].z + tmp.hv[xx].z ) / 2.0f; tmp1.color[x2 + 1].x = ( tmp.color[x].x + tmp.color[xx].x ) / 2.0f; tmp1.color[x2 + 1].y = ( tmp.color[x].y + tmp.color[xx].y ) / 2.0f; tmp1.color[x2 + 1].z = ( tmp.color[x].z + tmp.color[xx].z ) / 2.0f; tmp1.velocity[x2 + 1].x = ( tmp.velocity[x].x + tmp.velocity[xx].x ) / 2.0f; tmp1.velocity[x2 + 1].y = ( tmp.velocity[x].y + tmp.velocity[xx].y ) / 2.0f; tmp1.velocity[x2 + 1].z = ( tmp.velocity[x].z + tmp.velocity[xx].z ) / 2.0f; } tmp1.hv[60] = h.hv[29]; tmp1.color[60] = h.color[29]; tmp1.velocity[60] = h.velocity[29]; smooth_hair( &tmp1, 60 ); } if( tmp.segs == 5 ) { int x1 = 0; for( x = 0; x < 15; x = x + 3 ) { tmp.hv[x1] = h.hv[x]; tmp.color[x1] = h.color[x]; tmp.velocity[x1] = h.velocity[x]; x1++; } memcpy( &tmp1, &tmp, sizeof( RENDERHAIR ) ); } tmp1.kink = h.kink; //tmp1.kinkroot=h.kinkroot; tmp1.kinkfreq = h.kinkfreq; tmp1.ambient = h.ambient; tmp1.restlength = h.restlength; tmp1.norm = h.norm; tmp1.cutlength = h.cutlength; tmp1.dreadcount = h.dreadcount; tmp1.dreadtip = h.dreadtip; tmp1.dreadroot = h.dreadroot; tmp1.norm = h.norm; tmp.thickness = h.thickness; zero.x = zero.x - tmp1.hv[0].x; zero.y = zero.y - tmp1.hv[0].y; zero.z = zero.z - tmp1.hv[0].z; for( x = 0; x < 56; x++ ) { tmp1.hv[x].x += zero.x; tmp1.hv[x].y += zero.y; tmp1.hv[x].z += zero.z; ret->hv[x] = tmp1.hv[x]; ret->velocity[x] = tmp1.velocity[x]; ret->color[x] = tmp1.color[x]; } ret->kink = h.kink; ret->kinkfreq = h.kinkfreq; ret->ambient = h.ambient; ret->restlength = tmp1.restlength; ret->norm = h.norm; ret->cutlength = tmp1.cutlength; ret->dreadcount = tmp1.dreadcount; ret->dreadtip = tmp1.dreadtip; ret->dreadroot = tmp1.dreadroot; ret->norm = h.norm; ret->segs = tmp1.segs; //color_a_hair(&h); //// this was commented out ret->mtl = tmp.mtl; ret->thickness = h.thickness; ret->thicknesstip = h.thicknesstip; ret->diffuse = h.diffuse; ret->ambient = h.ambient; ret->spec = h.spec; ret->kspec = h.kspec; ret->restlength = Distance( ret->hv[1], ret->hv[2] ); ret->norm = h.norm; ret->slgroup = h.slgroup; ret->pid = h.pid; ret->vid = h.vid; //return (tmp1); } //#include "LWfur.c" static float VDot( VERT, VERT ); static BASEHAIR interp( BASEHAIR aa, BASEHAIR bb, float u ) { int x; BASEHAIR ret, tmphair; float du, dv; int breakit = 0; float dx, dy, dz; int stp = 1; // ret=aa; if( u > .995f ) u = .995f; if( aa.hv[0].z == bb.hv[0].z ) { stp = 1; } memcpy( &ret, &aa, sizeof( BASEHAIR ) ); dx = bb.norm.x - aa.norm.x; dy = bb.norm.y - aa.norm.y; dz = bb.norm.z - aa.norm.z; ret.norm.x = aa.norm.x + dx * u; ret.norm.y = aa.norm.y + dy * u; ret.norm.z = aa.norm.z + dz * u; ret.restlength = aa.restlength * ( 1 - u ) + bb.restlength * u; ret.multasp = aa.multasp * ( 1 - u ) + bb.multasp * u; ret.offset = aa.offset * ( 1 - u ) + bb.offset * u; ret.aspect = aa.aspect * ( 1 - u ) + bb.aspect * u; ret.norm = Vnorm( ret.norm ); ret.mtl = aa.mtl; ret.handle = aa.handle; for( x = 0; x < 60; x++ ) // interpolate sliders { dx = bb.slider[x] - aa.slider[x]; ret.slider[x] = aa.slider[x] + dx * u; } ret.cutlength = ret.slider[29]; breakit = 0; if( global_segs == 5 ) stp = 3; if( aa.mtl != bb.mtl ) breakit = 1; if( aa.splitgroup != bb.splitgroup ) breakit = 1; if( ( aa.splitmerge == 1 ) && ( bb.splitmerge == 1 ) ) breakit = 0; // merge override for( x = 0; x < 15; x += stp ) { float dx, dy, dz; dx = bb.hv[x].x - aa.hv[x].x; dy = bb.hv[x].y - aa.hv[x].y; dz = bb.hv[x].z - aa.hv[x].z; du = bb.uu - aa.uu; dv = bb.vv - aa.vv; // d=distance(aa.hv[x],bb.hv[x]); // ret.color[x]=aa.color[x]; ret.hv[x].x = aa.hv[x].x + dx * u; ret.hv[x].y = aa.hv[x].y + dy * u; ret.hv[x].z = aa.hv[x].z + dz * u; dx = bb.velocity[x].x - aa.velocity[x].x; dy = bb.velocity[x].y - aa.velocity[x].y; dz = bb.velocity[x].z - aa.velocity[x].z; ret.velocity[x].x = aa.velocity[x].x + dx * u; ret.velocity[x].y = aa.velocity[x].y + dy * u; ret.velocity[x].z = aa.velocity[x].z + dz * u; dx = bb.noisev[x].x - aa.noisev[x].x; dy = bb.noisev[x].y - aa.noisev[x].y; dz = bb.noisev[x].z - aa.noisev[x].z; ret.noisev[x].x = aa.noisev[x].x + dx * u; ret.noisev[x].y = aa.noisev[x].y + dy * u; ret.noisev[x].z = aa.noisev[x].z + dz * u; ret.uu = aa.uu + du * u; ret.vv = aa.vv + dv * u; } ret.vid = aa.vid; dx = bb.restlength - aa.restlength; ret.restlength = aa.restlength + dx * u; tmphair = ret; tmphair.handle = ret.handle; memcpy( &tmphair, &ret, sizeof( BASEHAIR ) ); if( breakit == 1 ) { int qq; float toss; toss = ( float ) 1.0f - u; //(float)drand98(); toss += ( ( float ) drand98( ) * ( float ) .6 - ( float ) .3 ); if( toss > .5 ) { ret = aa; for( qq = 0; qq < 15; qq++ ) { float uu; uu = ( float ) qq / ( float ) 15.0f; ret.hv[qq].x -= aa.hv[0].x; ret.hv[qq].y -= aa.hv[0].y; ret.hv[qq].z -= aa.hv[0].z; ret.noisev[qq].x -= aa.noisev[0].x; ret.noisev[qq].y -= aa.noisev[0].y; ret.noisev[qq].z -= aa.noisev[0].z; ret.uu -= aa.uu; ret.vv -= aa.vv; ret.hv[qq].x += tmphair.hv[0].x; ret.hv[qq].y += tmphair.hv[0].y; ret.hv[qq].z += tmphair.hv[0].z; ret.hv[qq].x = ret.hv[qq].x * ( ( float ) 1.0f - uu ) + aa.hv[qq].x * ( uu ); ret.hv[qq].y = ret.hv[qq].y * ( ( float ) 1.0f - uu ) + aa.hv[qq].y * ( uu ); ret.hv[qq].z = ret.hv[qq].z * ( ( float ) 1.0f - uu ) + aa.hv[qq].z * ( uu ); ret.noisev[qq].x = ret.noisev[qq].x * ( ( float ) 1.0f - uu ) + aa.noisev[qq].x * ( uu ); ret.noisev[qq].y = ret.noisev[qq].y * ( ( float ) 1.0f - uu ) + aa.noisev[qq].y * ( uu ); ret.noisev[qq].z = ret.noisev[qq].z * ( ( float ) 1.0f - uu ) + aa.noisev[qq].z * ( uu ); ret.handle.x = ret.handle.x * ( 1.0f - uu ) + aa.handle.x * uu; ret.handle.y = ret.handle.y * ( 1.0f - uu ) + aa.handle.y * uu; ret.handle.z = ret.handle.z * ( 1.0f - uu ) + aa.handle.z * uu; ret.multasp=aa.multasp; ret.offset=aa.offset; ret.aspect=aa.aspect; ret.uu = ret.uu * ( ( float ) 1.0f - uu ) + aa.uu * uu; ret.vv = ret.vv * ( ( float ) 1.0f - uu ) + aa.vv * uu; ret.mtl = aa.mtl; } } if( toss < .5 ) { ret = bb; for( qq = 0; qq < 15; qq++ ) { float uu; uu = ( float ) qq / ( float ) 15.0f; ret.hv[qq].x -= bb.hv[0].x; ret.hv[qq].y -= bb.hv[0].y; ret.hv[qq].z -= bb.hv[0].z; ret.noisev[qq].x -= bb.noisev[0].x; ret.noisev[qq].y -= bb.noisev[0].y; ret.noisev[qq].z -= bb.noisev[0].z; ret.hv[qq].x += tmphair.hv[0].x; ret.hv[qq].y += tmphair.hv[0].y; ret.hv[qq].z += tmphair.hv[0].z; ret.uu -= bb.uu; ret.uu += tmphair.uu; ret.vv -= bb.vv; ret.vv += tmphair.vv; ret.mtl = bb.mtl; ret.hv[qq].x = ret.hv[qq].x * ( 1.0f - uu ) + bb.hv[qq].x * ( uu ); ret.hv[qq].y = ret.hv[qq].y * ( 1.0f - uu ) + bb.hv[qq].y * ( uu ); ret.hv[qq].z = ret.hv[qq].z * ( 1.0f - uu ) + bb.hv[qq].z * ( uu ); ret.noisev[qq].x = ret.noisev[qq].x * ( ( float ) 1.0f - uu ) + bb.noisev[qq].x * ( uu ); ret.noisev[qq].y = ret.noisev[qq].y * ( ( float ) 1.0f - uu ) + bb.noisev[qq].y * ( uu ); ret.noisev[qq].z = ret.noisev[qq].z * ( ( float ) 1.0f - uu ) + bb.noisev[qq].z * ( uu ); ret.handle.x = ret.handle.x * ( 1.0f - uu ) + bb.handle.x * uu; ret.handle.y = ret.handle.y * ( 1.0f - uu ) + bb.handle.y * uu; ret.handle.z = ret.handle.z * ( 1.0f - uu ) + bb.handle.z * uu; ret.multasp=bb.multasp; ret.aspect=bb.aspect; ret.offset=bb.offset; ret.uu = ret.uu * ( ( float ) 1.0f - uu ) + bb.uu * uu; ret.vv = ret.vv * ( ( float ) 1.0f - uu ) + bb.vv * uu; } } } return ( ret ); } static BASEHAIR interp9( BASEHAIR aa, BASEHAIR bb, float u ) { int x; BASEHAIR ret, tmphair; float du, dv; int breakit = 0; float dx, dy, dz; int stp = 1; // ret=aa; if( aa.hv[0].z == bb.hv[0].z ) { stp = 1; } memcpy( &ret, &aa, sizeof( BASEHAIR ) ); dx = bb.norm.x - aa.norm.x; dy = bb.norm.y - aa.norm.y; dz = bb.norm.z - aa.norm.z; ret.norm.x = aa.norm.x + dx * u; ret.norm.y = aa.norm.y + dy * u; ret.norm.z = aa.norm.z + dz * u; ret.norm = Vnorm( ret.norm ); ret.mtl = aa.mtl; for( x = 0; x < 60; x++ ) // interpolate sliders { dx = bb.slider[x] - aa.slider[x]; ret.slider[x] = aa.slider[x] + dx * u; } ret.cutlength = ret.slider[29]; breakit = 0; if( global_segs == 5 ) stp = 3; if( aa.mtl != bb.mtl ) breakit = 1; if( aa.splitgroup != bb.splitgroup ) breakit = 1; if( ( aa.splitmerge == 1 ) && ( bb.splitmerge == 1 ) ) breakit = 0; // merge override for( x = 0; x < 15; x += stp ) { float dx, dy, dz; dx = bb.hv[x].x - aa.hv[x].x; dy = bb.hv[x].y - aa.hv[x].y; dz = bb.hv[x].z - aa.hv[x].z; du = bb.uu - aa.uu; dv = bb.vv - aa.vv; // d=distance(aa.hv[x],bb.hv[x]); // ret.color[x]=aa.color[x]; ret.hv[x].x = aa.hv[x].x + dx * u; ret.hv[x].y = aa.hv[x].y + dy * u; ret.hv[x].z = aa.hv[x].z + dz * u; ret.uu = aa.uu + du * u; ret.vv = aa.vv + dv * u; dx = bb.velocity[x].x - aa.velocity[x].x; dy = bb.velocity[x].y - aa.velocity[x].y; dz = bb.velocity[x].z - aa.velocity[x].z; ret.hv[x].x = aa.velocity[x].x + dx * u; ret.hv[x].y = aa.velocity[x].y + dy * u; ret.hv[x].z = aa.velocity[x].z + dz * u; } ret.vid = aa.vid; dx = bb.restlength - aa.restlength; ret.restlength = aa.restlength + dx * u; tmphair = ret; if( breakit == 1 ) { int qq; float toss; toss = ( float ) 1.0f - u; //(float)drand98(); toss += ( ( float ) drand98( ) * ( float ) .6 - ( float ) .3 ); if( toss > .5 ) { ret = aa; for( qq = 0; qq < 15; qq++ ) { float uu; uu = ( float ) qq / ( float ) 15.0f; ret.hv[qq].x -= aa.hv[0].x; ret.hv[qq].y -= aa.hv[0].y; ret.hv[qq].z -= aa.hv[0].z; ret.uu -= aa.uu; ret.vv -= aa.vv; ret.hv[qq].x += tmphair.hv[0].x; ret.hv[qq].y += tmphair.hv[0].y; ret.hv[qq].z += tmphair.hv[0].z; ret.hv[qq].x = ret.hv[qq].x * ( ( float ) 1.0f - uu ) + aa.hv[qq].x * ( uu ); ret.hv[qq].y = ret.hv[qq].y * ( ( float ) 1.0f - uu ) + aa.hv[qq].y * ( uu ); ret.hv[qq].z = ret.hv[qq].z * ( ( float ) 1.0f - uu ) + aa.hv[qq].z * ( uu ); ret.uu = ret.uu * ( ( float ) 1.0f - uu ) + aa.uu * uu; ret.vv = ret.vv * ( ( float ) 1.0f - uu ) + aa.vv * uu; ret.mtl = aa.mtl; } } if( toss < .5 ) { ret = bb; for( qq = 0; qq < 15; qq++ ) { float uu; uu = ( float ) qq / ( float ) 15.0f; ret.hv[qq].x -= bb.hv[0].x; ret.hv[qq].y -= bb.hv[0].y; ret.hv[qq].z -= bb.hv[0].z; ret.hv[qq].x += tmphair.hv[0].x; ret.hv[qq].y += tmphair.hv[0].y; ret.hv[qq].z += tmphair.hv[0].z; ret.uu -= bb.uu; ret.uu += tmphair.uu; ret.vv -= bb.vv; ret.vv += tmphair.vv; ret.mtl = bb.mtl; ret.hv[qq].x = ret.hv[qq].x * ( 1.0f - uu ) + bb.hv[qq].x * ( uu ); ret.hv[qq].y = ret.hv[qq].y * ( 1.0f - uu ) + bb.hv[qq].y * ( uu ); ret.hv[qq].z = ret.hv[qq].z * ( 1.0f - uu ) + bb.hv[qq].z * ( uu ); ret.uu = ret.uu * ( ( float ) 1.0f - uu ) + bb.uu * uu; ret.vv = ret.vv * ( ( float ) 1.0f - uu ) + bb.vv * uu; } } } return ( ret ); } static BASEHAIR DBinterp( BASEHAIR aa, BASEHAIR bb, float u ) { int x; BASEHAIR ret, tmphair; float dx, dy, dz; int breakit = 0; int stp = 1; ret = aa; dx = bb.norm.x - aa.norm.x; dy = bb.norm.y - aa.norm.y; dz = bb.norm.z - aa.norm.z; ret.norm.x = aa.norm.x + dx * u; ret.norm.y = aa.norm.y + dy * u; ret.norm.z = aa.norm.z + dz * u; ret.mtl = aa.mtl; for( x = 0; x < 40; x++ ) // interpolate sliders { dx = bb.slider[x] - aa.slider[x]; ret.slider[x] = aa.slider[x] + dx * u; } ret.cutlength = ret.slider[29]; if( global_segs == 5 ) stp = 3; if( aa.splitgroup != bb.splitgroup ) breakit = 1; if( aa.splitmerge == 1 ) breakit = 0; // merge override if( bb.splitmerge == 1 ) breakit = 0; for( x = 0; x < 1; x += stp ) { float dx, dy, dz; dx = bb.hv[x].x - aa.hv[x].x; dy = bb.hv[x].y - aa.hv[x].y; dz = bb.hv[x].z - aa.hv[x].z; // d=distance(aa.hv[x],bb.hv[x]); // ret.color[x]=aa.color[x]; ret.hv[x].x = aa.hv[x].x + dx * u; ret.hv[x].y = aa.hv[x].y + dy * u; ret.hv[x].z = aa.hv[x].z + dz * u; } ret.vid = aa.vid; dx = bb.restlength - aa.restlength; ret.restlength = aa.restlength + dx * u; tmphair = ret; if( breakit == 1 ) { int qq; float toss; toss = 1.0f - u; //(float)drand98(); toss += ( ( float ) drand98( ) * .6 - .3 ); if( toss > .5 ) { ret = aa; for( qq = 0; qq < 15; qq += stp ) { float uu; uu = ( float ) qq / 15.0f; ret.hv[qq].x -= aa.hv[0].x; ret.hv[qq].y -= aa.hv[0].y; ret.hv[qq].z -= aa.hv[0].z; ret.hv[qq].x += tmphair.hv[0].x; ret.hv[qq].y += tmphair.hv[0].y; ret.hv[qq].z += tmphair.hv[0].z; ret.hv[qq].x = ret.hv[qq].x * ( 1.0f - uu ) + aa.hv[qq].x * ( uu ); ret.hv[qq].y = ret.hv[qq].y * ( 1.0f - uu ) + aa.hv[qq].y * ( uu ); ret.hv[qq].z = ret.hv[qq].z * ( 1.0f - uu ) + aa.hv[qq].z * ( uu ); } } if( toss < .5 ) { ret = bb; for( qq = 0; qq < 15; qq += stp ) { float uu; uu = ( float ) qq / 15.0f; ret.hv[qq].x -= bb.hv[0].x; ret.hv[qq].y -= bb.hv[0].y; ret.hv[qq].z -= bb.hv[0].z; ret.hv[qq].x += tmphair.hv[0].x; ret.hv[qq].y += tmphair.hv[0].y; ret.hv[qq].z += tmphair.hv[0].z; ret.hv[qq].x = ret.hv[qq].x * ( 1.0f - uu ) + bb.hv[qq].x * ( uu ); ret.hv[qq].y = ret.hv[qq].y * ( 1.0f - uu ) + bb.hv[qq].y * ( uu ); ret.hv[qq].z = ret.hv[qq].z * ( 1.0f - uu ) + bb.hv[qq].z * ( uu ); } } } ret.norm = Vnorm( ret.norm ); return ( ret ); } static BASEHAIR subh( BASEHAIR aa, BASEHAIR bb ) { int x; for( x = 0; x < 15; x++ ) { aa.hv[x].x = aa.hv[x].x - bb.hv[x].x; aa.hv[x].y = aa.hv[x].y - bb.hv[x].y; aa.hv[x].z = aa.hv[x].z - bb.hv[x].z; } return ( aa ); } static BASEHAIR addh( BASEHAIR aa, BASEHAIR bb ) { int x; for( x = 0; x < 15; x++ ) { aa.hv[x].x = aa.hv[x].x + bb.hv[x].x; aa.hv[x].y = aa.hv[x].y + bb.hv[x].y; aa.hv[x].z = aa.hv[x].z + bb.hv[x].z; } return ( aa ); } static BASEHAIR displace( BASEHAIR hh ) { int x; for( x = 0; x < 15; x++ ) { float sc = 0.0f; float freq = 0.0f; // if (BOUNDLENGTH==0) BOUNDLENGTH=1; sc = ( restBOUNDLENGTH / 1.0 ); freq = ( restBOUNDLENGTH * 240.0 ); if( freq <= 0.0 ) freq = 1.0f; hh.hv[x].x += ( getnoise( hh.hv[x].x / freq, hh.hv[x].y / freq, hh.hv[x].z / freq ) - .5 ) * sc; hh.hv[x].y += ( getnoise( hh.hv[x].x / freq + 72.3, hh.hv[x].y / freq + 16.08, hh.hv[x].z / freq + 3.0 ) - .5 ) * sc; hh.hv[x].z += ( getnoise( hh.hv[x].x / freq + 15.0, hh.hv[x].y / freq + 19.99, hh.hv[x].z / freq + 12.0 ) - .5 ) * sc; } return ( hh ); } static BASEHAIR displace_random( BASEHAIR hh ) { int xx; for( xx = 0; xx < 15; xx++ ) { // float sc=0.0f; // float freq; hh.hv[xx].x += ( ( float ) drand98( ) - .5 ) * .00000001; hh.hv[xx].y += ( ( float ) drand98( ) - .5 ) * .00000001; hh.hv[xx].z += ( ( float ) drand98( ) - .5 ) * .00000001; } return ( hh ); } int MAYAquery_shave_ID( void ) { return ( (int)SHAVEID ); } static BASEHAIR displace_wiggle( BASEHAIR h, float ss, float freqq ) { int xx; VERT nn, dv; VERT aa, bb, cc; Matrix mr1, mr2, mr3, pm, ipm; float freq; if( totalfaces > 0 ) { if( ss > 0 ) if( freqq > 0 ) { aa.x = hair[facelist[face_start[h.pid] + 2]].resthv[0].x; aa.y = hair[facelist[face_start[h.pid] + 2]].resthv[0].y; aa.z = hair[facelist[face_start[h.pid] + 2]].resthv[0].z; bb.x = hair[facelist[face_start[h.pid]]].resthv[0].x; bb.y = hair[facelist[face_start[h.pid]]].resthv[0].y; bb.z = hair[facelist[face_start[h.pid]]].resthv[0].z; cc.x = hair[facelist[face_start[h.pid] + 1]].resthv[0].x; cc.y = hair[facelist[face_start[h.pid] + 1]].resthv[0].y; cc.z = hair[facelist[face_start[h.pid] + 1]].resthv[0].z; aa.x = aa.x - bb.x; aa.y = aa.y - bb.y; aa.z = aa.z - bb.z; aa = Vnorm( aa ); cc.x = cc.x - bb.x; cc.y = cc.y - bb.y; cc.z = cc.z - bb.z; cc = Vnorm( cc ); bb = Vcross( aa, cc ); bb = Vnorm( bb ); aa = Vcross( bb, cc ); mkmatrix2( pm, aa, bb, cc, cc ); inverse( pm, ipm ); freq = ( freqq / .04 ); // /((float)restBOUNDLENGTH); freq *= .25; nn = v[h.vid]; nn.x += gt * vnrest[h.vid].x * freq; nn.y += gt * vnrest[h.vid].y * freq; nn.z += gt * vnrest[h.vid].z * freq; ss *= ( 6.283f / 360.0f ) * 2.0f; ss *= 2.0f; dv.x = ( getnoise( nn.x * freq, nn.y * freq, nn.z * freq ) - .5 ) * ss; dv.y = ( getnoise( nn.x * freq + 72.3, nn.y * freq + 16.08, nn.z * freq + 3.0 ) - .5 ) * ss; dv.z = ( getnoise( nn.x * freq + 15.0, nn.y * freq + 19.99, nn.z * freq + 12.0 ) - .5 ) * ss; dv.x += ( getnoise( nn.x * freq * 4, nn.y * freq * 4, nn.z * freq * 4 ) - .5 ) * ss / 60.0f; dv.y += ( getnoise( nn.x * freq * 4 + 72.3, nn.y * freq * 4 + 16.08, nn.z * freq * 4 + 3.0 ) - .5 ) * ss / 60.0f; dv.z += ( getnoise( nn.x * 4 * freq + 15.0, nn.y * freq * 4 + 19.99, nn.z * freq * 4 + 12.0 ) - .5 ) * ss / 60.0f; { VERT dv2; dv2.x = 0; dv2.y = 0; dv2.z = 0; dv2.x = dv.x * .15; matrot( mr1, dv2 ); dv2.x = 0; dv2.y = 0; dv2.z = 0; dv2.y = dv.y * .7; matrot( mr2, dv2 ); dv2.x = 0; dv2.y = 0; dv2.z = 0; dv2.z = dv.z * .1; matrot( mr3, dv2 ); } //mk_polymat(pm,h.pid); //inverse(pm,ipm); for( xx = 1; xx < 15; xx++ ) if( h.pfID[xx] == -1 ) { h.hv[xx].x -= h.hv[0].x; h.hv[xx].y -= h.hv[0].y; h.hv[xx].z -= h.hv[0].z; h.hv[xx] = vxm( ipm, h.hv[xx] ); h.hv[xx] = vxm( mr1, h.hv[xx] ); h.hv[xx] = vxm( mr2, h.hv[xx] ); h.hv[xx] = vxm( mr3, h.hv[xx] ); h.hv[xx] = vxm( pm, h.hv[xx] ); h.hv[xx].x += h.hv[0].x; h.hv[xx].y += h.hv[0].y; h.hv[xx].z += h.hv[0].z; } } } return ( h ); } static BASEHAIR displace_clumpy2( BASEHAIR h, float ss, int cv ) { int xx; VERT dv; if( h.mtl == hair[cv].mtl ) if( ss > 0 ) for( xx = 0; xx < 15; xx++ ) { float d; dv.x = hair[cv].hv[xx].x - h.hv[xx].x; dv.y = hair[cv].hv[xx].y - h.hv[xx].y; dv.z = hair[cv].hv[xx].z - h.hv[xx].z; d = ( ( float ) xx / ( float ) 15.0 ); d *= ss; d = pow( d, 1.0 / 3.6 ); dv.x *= d; dv.y *= d; dv.z *= d; h.hv[xx].x += ( dv.x ); h.hv[xx].y += ( dv.y ); h.hv[xx].z += ( dv.z ); } return ( h ); } static void save_hair( CHNG name[599] ) { FILE *fp; int x, y, n, qq, a, b, g; fp = MYfopen( name, _T("w") ); if( fp ) { for( x = 0; x < totalverts; x++ ) { fprintf( fp, "h %d ", hair[x].vid ); for( y = 0; y < 15; y++ ) { fprintf( fp, "%f %f %f ", hair[x].hv[y].x, hair[x].hv[y].y, hair[x].hv[y].z ); } fprintf( fp, "\n" ); } qq = 0; for( x = 0; x < 4; x++ ) for( y = 0; y < 21; y++ ) fprintf( fp, "z %d %d %f\n", x, y, sliders[y][x].value ); fprintf( fp, "#model output by LipService\n" ); fprintf( fp, "\n" ); fprintf( fp, "g lserv\n" ); for( n = 0; n < totalverts; n++ ) { fprintf( fp, "v %f %f %f\n", v[qq * totalverts + n].x, v[qq * totalverts + n].y, v[qq * totalverts + n].z ); } fprintf( fp, "usemtl default\n" ); for( x = 0; x < totalgroups; x++ ) { fprintf( fp, "usemtl %s\n", group_names[x] ); for( a = 0; a < totalfaces; a++ ) { if( ( face_end[a] - face_start[a] ) > 0 ) { if( mtlgroup[a] == x ) { fprintf( fp, "f" ); for( b = face_start[a]; b < face_end[a]; b++ ) { g = facelist[b]; fprintf( fp, " %d", g + 1 ); } fprintf( fp, "\n" ); } } } } fprintf( fp, "\n" ); fprintf( fp, "\n" ); if( fp ) fclose( fp ); } } static void add_undo( void ) { int x, y; //printf ("add undo\n");fflush(stdout); if( totalhairfiles == 0 ) if( !Sundo ) { int n; n = total_splines; free( Sundo ); Sundo = NULL; if( n > 0 ) { Sundo = ( SMALLBASEHAIR * ) malloc( n * 4 * sizeof( SMALLBASEHAIR ) ); Sundo_totalverts = n; for( x = 0; x < n * 4; x++ ) Sundo[x].select[0] = -999; } //#endif } if( totalhairfiles == 0 ) // we're not rendering if( !undo ) { int n; //printf ("allocate undo\n");fflush(stdout); n = totalverts; free( undo ); undo = NULL; undo_totalverts = n; if( n > 0 ) { undo = ( SMALLBASEHAIR * ) malloc( 4 * n * sizeof( SMALLBASEHAIR ) ); for( x = 0; x < n * 4; x++ ) undo[x].select[0] = -999; } } if( undo ) if( totalverts != undo_totalverts ) { free( undo ); undo = NULL; undo_totalverts = -2; } if( Sundo ) if( totalverts != undo_totalverts ) { free( undo ); undo = NULL; undo_totalverts = -2; } if( totalverts == undo_totalverts ) if( undo ) { int q, qq; // DRAW_STATUS("captured geom for undo"); // for (y=1;y>=0;y--) for( qq = 4 - 1 - 1; qq >= 0; qq-- ) for( x = 0; x < totalverts; x++ ) { q = qq * totalverts; memcpy( &undo[x + q + totalverts], &undo[x + q], sizeof( SMALLBASEHAIR ) ); } for( x = 0; x < totalverts; x++ ) { int y; /// fix this memcpy( &undo[x], &hair[x], sizeof( BASEHAIR ) ); for( y = 0; y < 15; y++ ) { undo[x].hv[y] = hair[x].hv[y]; undo[x].select[y] = hair[x].select[y]; } } } if( total_splines == Sundo_totalverts ) if( Sundo ) { int q, qq; for( qq = 4 - 1 - 1; qq >= 0; qq-- ) for( x = 0; x < total_splines; x++ ) { q = qq * total_splines; memcpy( &Sundo[x + q + total_splines], &Sundo[x + q], sizeof( SMALLBASEHAIR ) ); } for( x = 0; x < total_splines; x++ ) { int y; for( y = 0; y < 15; y++ ) { Sundo[x].hv[y] = Shair[x].hv[y]; Sundo[x].select[y] = Shair[x].select[y]; } // fix this memcpy( &Sundo[x], &Shair[x], sizeof( BASEHAIR ) ); } } } static void clear_undo( void ) { int x, y; int t, qq; //printf ("clear undo\n");fflush(stdout); if( totalverts == undo_totalverts ) if( undo ) for( qq = 0; qq < 4; qq++ ) for( x = 0; x < totalverts; x++ ) { for( y = 0; y < 15; y++ ) { undo[x + qq * totalverts].hv[y] = hair[x].hv[y]; undo[x + qq * totalverts].select[y] = hair[x].select[y]; // memcpy( &undo[x + ( qq ) * totalverts], &hair[x], // sizeof( BASEHAIR ) ); } } if( total_splines == Sundo_totalverts ) if( Sundo ) for( qq = 0; qq < 4; qq++ ) for( x = 0; x < total_splines; x++ ) for( y = 0; y < 15; y++ ) { Sundo[x + qq * total_splines].hv[y] = Shair[x].hv[y]; Sundo[x + qq * total_splines].select[y] = Shair[x].select[y]; // memcpy( &undo[x + ( qq ) * totalverts], &hair[x], // sizeof( BASEHAIR ) ); } // memcpy( &Sundo[x + ( qq ) * total_splines], &Shair[x], // sizeof( BASEHAIR ) ); } static void undo_op( void ) { int x, y; refresh_OGL = 1; //printf ("undo op\n");fflush(stdout); if( totalverts == undo_totalverts ) if( undo ) { int qq, q; for( x = 0; x < totalverts; x++ ) { if( undo[x].select[0] >= 0 ) for( y = 0; y < 15; y++ ) { //printf ("we're undoing\n");fflush(stdout); hair[x].hv[y] = undo[x].hv[y]; hair[x].select[y] = undo[x].select[y]; // memcpy( &hair[x], &undo[x], sizeof( BASEHAIR ) ); } } for( qq = 0; qq < 4 - 1; qq++ ) for( x = 0; x < totalverts; x++ ) { q = qq * totalverts; { memcpy( &undo[x + q], &undo[x + q + totalverts], sizeof( SMALLBASEHAIR ) ); } } } if( total_splines == Sundo_totalverts ) if( Sundo ) { int qq, q; for( x = 0; x < total_splines; x++ ) { if( Sundo[x].select[0] >= 0 ) for( y = 0; y < 15; y++ ) { Shair[x].hv[y] = Sundo[x].hv[y]; Shair[x].select[y] = Sundo[x].select[y]; } // memcpy( &Shair[x], &Sundo[x], sizeof( BASEHAIR ) ); } for( qq = 0; qq < 4 - 1; qq++ ) for( x = 0; x < total_splines; x++ ) { q = qq * total_splines; memcpy( &Sundo[x + q], &Sundo[x + q + total_splines], sizeof( SMALLBASEHAIR ) ); } } Gbeen_scaled = 1; reset_rest( ); Gbeen_scaled = 0; } static void mkmatrix2( Matrix m, VERT xx, VERT yy, VERT zz, VERT b ); static void scale_freeze( void ) { int x; float span; float spanx, spanz; VERT a, b; // bounds for freeze a.x = 10000.0f; a.y = 10000.0f; a.z = 10000.0f; b.x = -10000.0f; b.y = -10000.0f; b.z = -10000.0f; // make the bounds for hair a.x = 10000.0f; a.y = 10000.0f; a.z = 10000.0f; b.x = -10000.0f; b.y = -10000.0f; b.z = -10000.0f; // make the bounds for verts for( x = 0; x < freeze.totalverts; x++ ) { if( freeze.v[x].x < a.x ) a.x = freeze.v[x].x; if( freeze.v[x].y < a.y ) a.y = freeze.v[x].y; if( freeze.v[x].z < a.z ) a.z = freeze.v[x].z; if( freeze.v[x].x > b.x ) b.x = freeze.v[x].x; if( freeze.v[x].y > b.y ) b.y = freeze.v[x].y; if( freeze.v[x].z > b.z ) b.z = freeze.v[x].z; } a.y = 0; //span=b.y-a.y; //span=b.y; span = b.y; //if (a.y<0) span+=a.y; spanx = b.x - a.x; spanz = b.z - a.z; for( x = 0; x <= 66; x++ ) { VERT xv, yv, zv; Matrix m; // xv.x=span*1;xv.y=0;xv.z=0;xv=Vnorm(xv); // yv.x=0.0f;yv.y= span*1;yv.z=0; yv=Vnorm(yv); // zv.x=0.0f;zv.y=0;zv.z=span*1; zv=Vnorm(zv); xv.x = 1.0f; xv.y = 0; xv.z = 0; xv = Vnorm( xv ); yv.x = 0.0f; yv.y = 1.0f; yv.z = 0; yv = Vnorm( yv ); zv.x = 0.0f; zv.y = 0; zv.z = 1.0f; zv = Vnorm( zv ); matrixhair.restpos[x].x = 0; matrixhair.restpos[x].y = ( span / 56.0 ) * ( float ) x; //+a.y; // matrixhair.restpos[x].y=(span/50.0)*(float)x;//+a.y; matrixhair.restpos[x].z = 0; matrixhair.spanx = spanx; matrixhair.spanz = spanz; matrixhair.spany = span; mkmatrix2( m, xv, yv, zv, matrixhair.restpos[x] ); inverse( m, matrixhair.rest2zero[x] ); } for( x = 0; x < freeze.totalverts; x++ ) { float e; e = freeze.v[x].y; //-a.y; e /= span; //// e*=56.0f; e *= 50.0f; if( e < 0 ) e = 0; // e/=1.1; freeze.envelope[x].link1 = ( int ) floor( e ); freeze.envelope[x].v = ( e - floor( e ) ); if( freeze.envelope[x].link1 > 54 ) // 52 { freeze.envelope[x].link1 = 54; //52 freeze.envelope[x].v = 0; } freeze.envelope[x].link2 = freeze.envelope[x].link1 + 1; if( freeze.envelope[x].link2 > 55 ) freeze.envelope[x].link2 = 55; // 53 53 freeze.uv[x].x = ( freeze.v[x].x - a.x ) / spanx; freeze.uv[x].y = ( freeze.v[x].y ) / span; freeze.uv[x].z = ( freeze.v[x].z - a.z ) / spanz; // freeze.v[x].y-=floor(freeze.v[x].y); } } int SHAVEgetMAXPASSES( void ) { float maxp = 0; int x, y; for( x = 0; x < totalhairfiles; x++ ) for( y = 0; y < 5; y++ ) if( Gshavep[x].passes[y] > maxp ) maxp = Gshavep[x].passes[y]; MAXPASSES = maxp; return ( MAXPASSES ); } static void MTdraw_lotsWFROOT( int slg, int ind, VERT offs, int clone, BASEHAIR * outhair, CURVEINFO * cinfo, GLOBS * glots ); static void draw_lotsWFROOT( int slg, int ind, VERT offs, int clone, BASEHAIR * outhair, CURVEINFO * cinfo, int pass ) // we're just testing if this works { GLOBS *glots; glots = >hreads[0]; MTdraw_lotsWFROOT( slg, ind, offs, clone, outhair, cinfo, glots ); } static void MTdraw_lotsWF( int slg, int ind, VERT offs, int clone, BASEHAIR * outhair, CURVEINFO * cinfo, GLOBS * glots ); static void draw_lotsWF( int slg, int ind, VERT offs, int clone, BASEHAIR * outhair, CURVEINFO * cinfo ) // we're just testing if this works { GLOBS *glots,gll; glots = >hreads[0]; glots->Gcurpass = Gcurpass; glots->GhairID = ind; glots->Gslg = slg; glots->hairnumber = ind; glots->segs=15; glots->rs.Gflyaway_percent=Gflyaway_percent; glots->rs.Gsquirrel=Gsquirrel; glots->rs.Gclumps=Gclumps; ///glots->rs.Gkd=Gkd; MTdraw_lotsWF( slg, ind, offs, clone, outhair, cinfo, glots ); } static void draw_lotsWF2( int slg, int ind, VERT offs, int clone, BASEHAIR * outhair, CURVEINFO * cinfo ) // we're just testing if this works { GLOBS *glots,gll; glots = &gll; glots->Gcurpass = Gcurpass; glots->GhairID = ind; glots->Gslg = slg; glots->hairnumber = ind; glots->segs=15; MTdraw_lotsWF( slg, ind, offs, clone, outhair, cinfo, glots ); } // shownoise() //{ // int xx,y,ys,xs; // xs=580-55;ys=(570-45)-1; // for (xx=0;xx 0 ) { BOUNDX = 1000000000; BOUNDY = 1000000000; BOUNDZ = 1000000000; BOUND1X = -1000000000; BOUND1Y = -1000000000; BOUND1Z = -1000000000; if( total_splines == 0 ) if( totalverts > 0 ) for( x = 0; x < totalverts; x++ ) if( hair[x].restlength > 0 ) if( ( ( head >= 0 ) && ( hair[x].mtl == head ) ) || ( ( splines >= 0 ) && ( hair[x].mtl == splines ) ) ) // for( y = 0; y < 15; y++ ) for( y = 0; y < 1; y++ ) { if( hair[x].noisev[y].x > BOUND1X ) BOUND1X = hair[x].noisev[y].x; if( hair[x].noisev[y].y > BOUND1Y ) BOUND1Y = hair[x].noisev[y].y; if( hair[x].noisev[y].z > BOUND1Z ) BOUND1Z = hair[x].noisev[y].z; if( hair[x].noisev[y].x < BOUNDX ) BOUNDX = hair[x].noisev[y].x; if( hair[x].noisev[y].y < BOUNDY ) BOUNDY = hair[x].noisev[y].y; if( hair[x].noisev[y].z < BOUNDZ ) BOUNDZ = hair[x].noisev[y].z; } if( total_splines > 0 ) for( x = 0; x < total_splines; x++ ) if( Shair[x].restlength > 0 ) for( y = 0; y < 15; y++ ) // for( y = 0; y < 1; y++ ) { if( Sresthair[x].noisev[y].x > BOUND1X ) BOUND1X = Sresthair[x].noisev[y].x; if( Sresthair[x].noisev[y].y > BOUND1Y ) BOUND1Y = Sresthair[x].noisev[y].y; if( Sresthair[x].noisev[y].z > BOUND1Z ) BOUND1Z = Sresthair[x].noisev[y].z; if( Sresthair[x].noisev[y].x < BOUNDX ) BOUNDX = Sresthair[x].noisev[y].x; if( Sresthair[x].noisev[y].y < BOUNDY ) BOUNDY = Sresthair[x].noisev[y].y; if( Sresthair[x].noisev[y].z < BOUNDZ ) BOUNDZ = Sresthair[x].noisev[y].z; } { float big = 0; if( ( BOUND1X - BOUNDX ) > big ) big = BOUND1X - BOUNDX; if( ( BOUND1Y - BOUNDY ) > big ) big = BOUND1Y - BOUNDY; if( ( BOUND1Z - BOUNDZ ) > big ) big = BOUND1Z - BOUNDZ; } if( BOUNDX < BOUND1X ) { float dx, dy, dz; dx = BOUND1X - BOUNDX; dy = BOUND1Y - BOUNDY; dz = BOUND1Z - BOUNDZ; BOUNDLENGTH = fsqrt( dx * dx + dy * dy + dz * dz ); restBOUNDLENGTH = BOUNDLENGTH; } } if( restBOUNDLENGTH == 0 ) { BOUNDX = 1000000000; BOUNDY = 1000000000; BOUNDZ = 1000000000; BOUND1X = -1000000000; BOUND1Y = -1000000000; BOUND1Z = -1000000000; for( x = 0; x < Dtotalverts; x++ ) { if( Dv[x].x > BOUND1X ) BOUND1X = Dv[x].x; if( Dv[x].y > BOUND1Y ) BOUND1Y = Dv[x].y; if( Dv[x].z > BOUND1Z ) BOUND1Z = Dv[x].z; if( Dv[x].x < BOUNDX ) BOUNDX = Dv[x].x; if( Dv[x].y < BOUNDY ) BOUNDY = Dv[x].y; if( Dv[x].z < BOUNDZ ) BOUNDZ = Dv[x].z; } { float big = 0; if( ( BOUND1X - BOUNDX ) > big ) big = BOUND1X - BOUNDX; if( ( BOUND1Y - BOUNDY ) > big ) big = BOUND1Y - BOUNDY; if( ( BOUND1Z - BOUNDZ ) > big ) big = BOUND1Z - BOUNDZ; } if( BOUNDX < BOUND1X ) { float dx, dy, dz; dx = BOUND1X - BOUNDX; dy = BOUND1Y - BOUNDY; dz = BOUND1Z - BOUNDZ; BOUNDLENGTH = fsqrt( dx * dx + dy * dy + dz * dz ); restBOUNDLENGTH = BOUNDLENGTH; } } } static void initbounds( void ) { int x; int y = 0; mkbounds( ); } static void mkbounds2( void ) { int x; int y; restBOUNDLENGTH = 0; BOUNDLENGTH = 0; mkbounds( ); } static void init_hair( void ) { int x; if( Dtotalverts > 0 ) { DRAW_STATUS( "running auto-groom" ); // make_normals(); initbounds( ); //reset_faces(); //checkforzero(); regroup( ); skull_sphere = -1; for( x = 0; x < totalverts; x++ ) { int y; hair[x].vid = x; hair[x].restlength = 0.0f; for( y = 0; y < 15; y++ ) hair[x].hv[y] = v[x]; hair[x].mtl = vertgroup[x]; hair[x].slgroup = vertgroup[x]; } // grow hairs { int q; for( q = 0; q < totalgroups; q++ ) group_enable[q] = 0; for( q = 0; q < totalgroups; q++ ) { if( ( group_names[q][0] == 'b' ) && ( group_names[q][1] == 'e' ) && ( group_names[q][2] == 'a' ) && ( group_names[q][3] == 'r' ) && ( group_names[q][4] == 'd' ) ) { beard = q; group_enable[q] = 1; } if( ( group_names[q][0] == 's' ) && ( group_names[q][1] == 'k' ) && ( group_names[q][2] == 'u' ) && ( group_names[q][3] == 'l' ) ) { skull_sphere = q; group_enable[q] = 2; } if( ( group_names[q][0] == 's' ) && ( group_names[q][1] == 'p' ) && ( group_names[q][2] == 'l' ) && ( group_names[q][3] == 'i' ) && ( group_names[q][4] == 'n' ) ) { splines = q; group_enable[q] = 1; } if( ( group_names[q][0] == 'h' ) && ( group_names[q][1] == 'a' ) && ( group_names[q][2] == 'i' ) && ( group_names[q][3] == 'r' ) ) { head = q; group_enable[q] = 1; } if( ( group_names[q][0] == 'e' ) && ( group_names[q][1] == 'y' ) && ( group_names[q][2] == 'e' ) && ( group_names[q][3] == 'b' ) && ( group_names[q][4] == 'r' ) ) { eyebrow = q; group_enable[q] = 1; } if( ( group_names[q][0] == 'e' ) && ( group_names[q][1] == 'y' ) && ( group_names[q][2] == 'e' ) && ( group_names[q][3] == 'l' ) && ( group_names[q][4] == 'a' ) ) { eyelash = q; group_enable[q] = 1; } } make_normals( ); for( q = 0; q < totalverts; q++ ) hair[q].resthv[0] = v[q]; { /// int fv,lst,tv; for( q = 0; q < totalverts; q++ ) { int en; en = 0; if( skull_sphere == hair[q].mtl ) // for (fv=face_start[q];fv0)||(LOCAL_SHADCNT[4]>0)) { int q, fv, en; // if (0==1) // what the hell is this??? // for (q=0;q0)||(LOCAL_SHADCNT[0]>0)) { int q, fv, en; // if (0==1) // what the hell is this??? // for (q=0;q= 0 ) for( fv = face_start[q]; fv < face_end[q]; fv++ ) { int g; en = 1; g = facelist[fv]; { hair[g].mtl = mtlgroup[q]; } } if( splines == mtlgroup[q] ) if( splines >= 0 ) for( fv = face_start[q]; fv < face_end[q]; fv++ ) { int g; en = 1; g = facelist[fv]; { hair[g].mtl = mtlgroup[q]; } } if( en == 0 ) group_stat[mtlgroup[q]] = 2; } } } for( x = 0; x < totalverts; x++ ) { int qqq; if( ( ( hair[x].mtl != head ) && ( hair[x].mtl != eyebrow ) && ( hair[x].mtl != eyelash ) && ( hair[x].mtl != splines ) && ( hair[x].mtl != beard ) ) || ( hair[x].restlength == 0.0f ) ) { for( qqq = 0; qqq < 15; qqq++ ) { hair[x].hv[qqq] = v[x]; } } } center_select( ); reset_faces( ); mkbounds( ); texture_bounds( ); // weight_polys( ); global_lastID = -1; mkHandles( ); } // end hairstuff static void freeverts( void ) { // totalverts=0; // totallines=0; //int x; //if (vn!=NULL) global_lastID = -1; // if( v != NULL ) // if( totalverts > 0 ) // this is questionable .. { // if( Guv) free_geomWF( &Guv ); // Guv=NULL; if( hair != NULL) free( hair ); // hair=NULL; //Nfree(hairvelocity); //Nfree(lasthair); //Nfree(resthair); //Nfree(thishair); if( vnrest != NULL ) free( vnrest ); vnrest=NULL; //totalverts=0; //#ifdef DOUNDO //#ifndef LIB // printf ("undo SHAVEID / lsSHAVEID %d %d %d\n",undo,SHAVEID,lsSHAVEID);fflush(stdout); //#endif //#endif if (totalhairfiles>0) { if( undo ) { free( undo ); undo = NULL; } if( Sundo ) { free( Sundo ); Sundo = NULL; } } if( v ) free( v ); v=NULL; // Nfree( ucord ); // Nfree( vcord ); if( bk ) free( bk ); bk=NULL; //Nfree(spare); // Nfree(spare2); if( vn ) free( vn ); vn=NULL; if( neutral ) free( neutral ); neutral=NULL; if( pbtag ) free( pbtag ); pbtag=NULL; if( vertgroup ) free( vertgroup ); vertgroup=NULL; if( tagvert ) free( tagvert ); tagvert=NULL; if( rvcolor ) free( rvcolor ); rvcolor=NULL; if( gvcolor ) free( gvcolor ); gvcolor=NULL; if( bvcolor ) free( bvcolor ); bvcolor=NULL; if( facelist ) free( facelist ); facelist=NULL; if( face_start ) free( face_start ); face_start=NULL; if( face_end ) free( face_end ); face_end=NULL; if( poly_weight ) free( poly_weight ); poly_weight=NULL; if( mtlgroup ) free( mtlgroup ); mtlgroup=NULL; vn = NULL; mtlgroup = NULL; poly_weight = NULL; face_end = NULL; face_start = NULL; facelist = NULL; bvcolor = NULL; gvcolor = NULL; rvcolor = NULL; tagvert = NULL; vertgroup = NULL; pbtag = NULL; neutral = NULL; vn = NULL; bk = NULL; v = NULL; hair = NULL; vnrest = NULL; // undo=NULL; totalverts = 0; totalfaces = 0; totalfverts = 0; } } static void initverts( void ) { // totalverts=0; // totallines=0; //int x; //if (vn!=NULL) global_lastID = -1; // if( v != NULL ) // if( totalverts > 0 ) // this is questionable .. // if( Guv) // Guv=NULL; hair=NULL; //Nfree(hairvelocity); //Nfree(lasthair); //Nfree(resthair); //Nfree(thishair); vnrest=NULL; //totalverts=0; //#ifdef DOUNDO //#ifndef LIB // printf ("undo SHAVEID / lsSHAVEID %d %d %d\n",undo,SHAVEID,lsSHAVEID);fflush(stdout); //#endif //#endif undo = NULL; Sundo = NULL; v=NULL; bk=NULL; vn=NULL; neutral=NULL; pbtag=NULL; vertgroup=NULL; tagvert=NULL; rvcolor=NULL; gvcolor=NULL; bvcolor=NULL; facelist=NULL; face_start=NULL; face_end=NULL; poly_weight=NULL; mtlgroup=NULL; vn = NULL; mtlgroup = NULL; poly_weight = NULL; face_end = NULL; face_start = NULL; facelist = NULL; bvcolor = NULL; gvcolor = NULL; rvcolor = NULL; tagvert = NULL; vertgroup = NULL; pbtag = NULL; neutral = NULL; vn = NULL; bk = NULL; v = NULL; hair = NULL; vnrest = NULL; // undo=NULL; totalverts = 0; totalfaces = 0; totalfverts = 0; } static int lashtotal = 0; static int headtotal = 0; static int beardtotal = 0; static int browtotal = 0; static int *head_face = NULL; static int *beard_face = NULL; static int *brow_face = NULL; static int *lash_face = NULL; void clear_shave_engine( void ) { Dfreeverts( ); freeverts( ); free_freeze( ); free_splines( ); // SNfree( ); freevox( ); Dtotalverts = 0; Stotalverts = 0; totalverts = 0; total_splines = 0; SHAVEclear_stack( ); // if (Gindex) free(Gindex); // Gindex=NULL; //kd_free(Gkd); // Gkd=NULL; // Gkd=NULL; } #include static void xformcontrolhair( void ) { int *tmphit; int x; VERT pbig, psmall; // rest in the x, and current in the y comps float ascalr = 0; float ascalh = 0; pbig.x = 0; pbig.y = 0; psmall.x = 100000; psmall.y = 100000; ascalr = 1.0f; //ascalh=ascalr*global_scale; ascalh = 1.0f; // ascalr=1.0f; // ascalh=global_scale; tmphit = ( int * ) malloc( sizeof( int ) * totalverts ); Dmake_normals( ); make_normals( ); for( x = 0; x < totalverts; x++ ) hair[x].norm = vn[x]; // for (x=0;x0) for (x=0;x=face_end[x]) g=face_start[x]; g=facelist[g]; hair[facelist[y]].neighbor_guide=g; } } if (Gslg==4) for (x=0;xtotal_splines-1) g=total_splines-1; Shair[y].neighbor_guide=g; } } MTxform_kernal(); } static void MTxformcontrolhair( int x) { int *tmphit; VERT pbig, psmall; // rest in the x, and current in the y comps float ascalr = 0; float ascalh = 0; pbig.x = 0; pbig.y = 0; psmall.x = 100000; psmall.y = 100000; ascalr = 1.0f; //ascalh=ascalr*global_scale; ascalh = 1.0f; // ascalr=1.0f; // ascalh=global_scale; // tmphit = ( int * ) malloc( sizeof( int ) * totalverts ); // Dmake_normals( ); // make_normals( ); // for( x = 0; x < totalverts; x++ ) if (totalverts>0) hair[x].norm = vn[x]; // for (x=0;x0) { int g; // tmphit[x] = 0; // if (hair[x].restlength<0.001f) { hair[x].restlength=0.0f;for (g=0;g<15;g++) hair[x].hv[g]=v[x];} //for (x=0;x= 3 ) // for( r = face_start[x]; r < face_end[x]; r++ ) { float rl; int g; int g1; // g1 = facelist[face_start[x]]; // g = facelist[r]; g = x; if (g>=0 && g 0.0001f ) { VERT *rhq1, *rhq2, *rhg1, *rhg2; int q1, q2; g1=hair[g].neighbor_guide; rhq1 = &hair[g].resthv[0]; rhq2 = &hair[g1].resthv[0]; // rhg1 = &hair[g1].resthv[0]; xv.x = rhq1->x - rhq2->x; xv.y = rhq1->y - rhq2->y; xv.z = rhq1->z - rhq2->z; xv = Vnorm( xv ); yv = Vnorm( vnrest[g] ); // g is uninitialized?? zv = Vnorm( Vcross( yv, xv ) ); zv=Vnorm(zv);// xv = Vcross( yv, zv );// xv = Vnorm( xv );// zv = Vcross( yv, xv );// zv = Vnorm( zv );// { // float dd; d1 = ascalr; if( d1 != 0 ) rl = hair[g].restlength / d1; else rl = 0; } b = hair[g].resthv[0]; t1 = b; mkmatrix( tmpmat, xv, yv, zv, b ); inverse( tmpmat, rp2zero ); // rhq1 = &hair[q1].hv[0]; // rhq2 = &hair[q2].hv[0]; // rhg1 = &hair[g1].hv[0]; rhq1 = &v[g]; rhq2 = &v[g1]; xv.x = rhq1->x - rhq2->x; xv.y = rhq1->y - rhq2->y; xv.z = rhq1->z - rhq2->z; xv = Vnorm( xv ); yv = Vnorm( vn[g] ); // g is uninitialized?? zv = Vnorm( Vcross( yv, xv ) ); zv=Vnorm(zv);// xv = Vcross( yv, zv );// xv = Vnorm( xv );// zv = Vcross( yv, xv );// zv = Vnorm( zv );// #ifdef crap xv.x = rhq2->x - rhg1->x; xv.y = rhq2->y - rhg1->y; xv.z = rhq2->z - rhg1->z; zv.x = rhq2->x - rhg1->x; zv.y = rhq2->y - rhg1->y; zv.z = rhq2->z - rhg1->z; xv = Vnorm( xv ); zv = Vnorm( zv ); yv = Vnorm( Vcross( xv, zv ) ); // yv = vn[g]; xv = Vcross( yv, zv );// xv = Vnorm( xv );// zv = Vcross( yv, xv );// zv = Vnorm( zv );// #endif { d2 = ascalh; rl *= d2; } // b = hair[g].hv[0]; b = v[g]; t2 = b; mkmatrix( zero2wp, xv, yv, zv, b ); for( yy = 0; yy < 15; yy++ ) if( hair[g].pfID[yy] < 0 ) { BASEHAIR h; h.hv[yy].x = hair[g].resthv[yy].x - t1.x; h.hv[yy].y = hair[g].resthv[yy].y - t1.y; h.hv[yy].z = hair[g].resthv[yy].z - t1.z; if( ( d1 > 0 ) && ( d2 > 0 ) ) { h.hv[yy].x /= d1; h.hv[yy].y /= d1; h.hv[yy].z /= d1; } // scale the hair if( hair[g].restlength != 0 ) { h.hv[yy] = vxm( rp2zero, h.hv[yy] ); if( hair[g].pfID[yy] < 0 ) hair[g].hv[yy] = vxm( zero2wp, h.hv[yy] ); } else { int xxx; hair[g].hv[0] = v[g]; for( xxx = 0; xxx < 15; xxx++ ) hair[g].hv[xxx] = hair[g].hv[0]; } if( ( d1 > 0 ) && ( d2 > 0 ) ) if( hair[g].pfID[yy] < 0 ) if( ( d1 > 0 ) && ( d2 > 0 ) ) { hair[g].hv[yy].x *= d2; hair[g].hv[yy].y *= d2; hair[g].hv[yy].z *= d2; } // scale the hair if( hair[g].pfID[yy] < 0 ) { hair[g].hv[yy].x = hair[g].hv[yy].x + t2.x; hair[g].hv[yy].y = hair[g].hv[yy].y + t2.y; hair[g].hv[yy].z = hair[g].hv[yy].z + t2.z; hair[g].restlength = ( hair[g].restlength ) * d2; } // hair[g]=resthair[g]; } // tmphit[g] = 1; } } } // free( tmphit ); if (total_splines>0) // for( x = 0; x < total_splines; x++ ) { extract_chain( &Shair[x] ); } restore_locked_hair( x ); // mkbounds( ); // for( x = 0; x < totalverts; x++ ) if (totalverts>0) if( hair[x].restlength < 0.0001f ) { int y; VERT qq; hair[x].restlength = 0.0f; hair[x].sparerestlength = 0.0f; qq = v[x]; #ifdef MAX3D //qq.z*= -1.0f; #endif for( y = 0; y < 15; y++ ) hair[x].hv[y] = qq; } MTxformHandles( x ); } static void LORESallocvert( int n, int f, int fll ) //int n,f; { int x; int on, of; if (n>0) { sculpt.x = 100.0f; sculpt.y = 100.0f; sculpt.z = 170.0f; vn = NULL; mtlgroup = NULL; poly_weight = NULL; face_end = NULL; face_start = NULL; facelist = NULL; bvcolor = NULL; gvcolor = NULL; rvcolor = NULL; tagvert = NULL; vertgroup = NULL; pbtag = NULL; neutral = NULL; vn = NULL; bk = NULL; v = NULL; hair = NULL; vnrest = NULL; // undo=NULL; on = n + 1; of = f; // n += 5; hmm - why we doing this? // f += 5; // fll += 5; freeverts( ); // n*=5; // f=(int)(f*6); // fll*=6; // n*=1; //// f+=500; //// fll+=500; //// n+=500; /// f*=2; // fll+=totalfacesSP*300; // f+=totalfacesSP*2; // n+=totalfacesSP*300; // f+=total_splines*2; // fll+=total_splines*300; // n+=total_splines*300; // if (fll<500) fll=500; // if (f<100) f=100; // if (n<500) n=500; if( splines != -1 ) { // n+=200; // f+=100; // fll+=4500; } // printf ("allocating verts\n"); ////if (n<1000) n=1000; ////if (f<2000) f=2000; //if (f>0) { int y; for( x = 0; x < 5; x++ ) for( y = 0; y < f; y++ ) slgfaces[x][y] = 0; } //if (n>0) { //hairvelocity=(BASEHAIR *) malloc (n*sizeof(BASEHAIR)); //lasthair=(BASEHAIR *) malloc (n*sizeof(BASEHAIR)); //resthair=(BASEHAIR *) malloc (n*sizeof(BASEHAIR)); //thishair=(BASEHAIR *) malloc (n*sizeof(BASEHAIR)); if( n != 0 ) { rvcolor = ( float * ) malloc( n * sizeof( float ) ); gvcolor = ( float * ) malloc( n * sizeof( float ) ); bvcolor = ( float * ) malloc( n * sizeof( float ) ); //#ifdef DOUNDO //if (make_undo) //#ifndef LIB //#endif //#endif v = ( VERT * ) malloc( n * sizeof( VERT ) ); // ucord = ( float * )malloc( n * sizeof( float ) ); // vcord = ( float * )malloc( n * sizeof( float ) ); vnrest = ( VERT * ) malloc( n * sizeof( VERT ) ); bk = ( VERT * ) malloc( n * sizeof( VERT ) ); //spare=(BASEHAIR *) malloc (n*sizeof(BASEHAIR)); //spare2=(BASEHAIR *) malloc (n*sizeof(BASEHAIR)); vn = ( VERT * ) malloc( n * sizeof( VERT ) ); neutral = ( VERT * ) malloc( n * sizeof( VERT ) ); pbtag = ( int * ) malloc( n * sizeof( int ) ); //vertgroup=(int *) malloc (n*sizeof(int)); vertgroup = ( int * ) malloc( n * sizeof( int ) ); tagvert = ( float * ) malloc( n * sizeof( float ) ); } } //if (n>0) { if( fll != 0 ) facelist = ( int * ) malloc( fll * 5 * sizeof( int ) ); //face_start=(int *) malloc (f*22*sizeof(int)); if( f != 0 ) poly_weight = ( double * ) malloc( f * 1 * sizeof( double ) ); if( f != 0 ) face_start = ( int * ) malloc( f * 1 * sizeof( int ) ); //face_end=(int *) malloc (f*22*sizeof(int)); if( f != 0 ) face_end = ( int * ) malloc( f * 1 * sizeof( int ) ); if( f != 0 ) mtlgroup = ( int * ) malloc( f * 1 * sizeof( int ) ); } //line_start=(int *) malloc (f*28*sizeof(int)); //line_faceref=(int *) malloc (f*28*sizeof(int)); //line_end=(int *) malloc (f*28*sizeof(int)); if( n != 0 ) hair = ( BASEHAIR * ) malloc( ( n + 5 ) * sizeof( BASEHAIR ) ); if( n > 0 ) if( hair == NULL ) { Glow_mem = 1; freeverts( ); Dfreeverts( ); DRAW_STATUS( "*** ERROR *** Out of Memory" ); n = 0; totalverts = 0; f = 0; totalfaces = 0; totalfverts = 0; } for( x = 0; x < n; x++ ) { int yy; for( yy = 0; yy < 15; yy++ ) hair[x].w[yy] = 0.0f; // ucord[x] = 0; // vcord[x] = 0; hair[x].index=0; hair[x].uu = 0; hair[x].vv = 0; hair[x].mtl = -10; hair[x].restlength = 0; hair[x].hide = 0; // hair[x].freechain = (char)0; hair[x].splitmerge = 0; hair[x].Bid1= -1; // initialize barycentrics hair[x].Bid2= -1; hair[x].Bid3= -1; hair[x].bw1=0.0f; hair[x].bw2=0.0f; hair[x].bw3=0.0f; vertgroup[x] = 0; for( yy = 0; yy < 60; yy++ ) hair[x].slider[yy] = 1.0f; // for (yy=0;yy<50;yy++) // resthair[x].slider[yy]=1.0f; for( yy = 0; yy < 15; yy++ ) { hair[x].pfID[yy] = -1; hair[x].select[yy] = 0; hair[x].velocity[yy].x = 0.0f; hair[x].velocity[yy].y = 0.0f; hair[x].velocity[yy].z = 0.0f; hair[x].noisev[yy].x = 0.0f; hair[x].noisev[yy].y = 0.0f; hair[x].noisev[yy].z = 0.0f; hair[x].resthv[yy].x = 0.0f; hair[x].resthv[yy].y = 0.0f; hair[x].resthv[yy].z = 0.0f; hair[x].lasthv[yy].x = 0.0f; hair[x].lasthv[yy].y = 0.0f; hair[x].lasthv[yy].z = 0.0f; hair[x].color[yy].x = 0.0f; hair[x].color[yy].y = 0.0f; hair[x].color[yy].z = 0.0f; //resthair[x].select[yy]=0; //resthair[x].velocity[yy].x=0.0f; //resthair[x].velocity[yy].y=0.0f; //resthair[x].velocity[yy].z=0.0f; //resthair[x].color[yy].x=0.0f; //resthair[x].color[yy].y=0.0f; //resthair[x].color[yy].z=0.0f; hair[x].select[yy] = 1.0f; //resthair[x].select[yy]=1.0f; hair[x].trim = 15; //resthair[x].trim=15; //thishair[x].trim=15; //lasthair[x].trim=15; } // hair[x].mtl=vertgroup[x]; // memcpy(&resthair[x],&hair[x],sizeof(BASEHAIR)); // memcpy(&thishair[x],&hair[x],sizeof(BASEHAIR)); // memcpy(&lasthair[x],&hair[x],sizeof(BASEHAIR)); } for( x = 0; x < f; x++ ) { face_start[x] = 0; face_end[x] = 0; facelist[x] = 0; mtlgroup[x] = 0; } } } static int find_closest_poly( VERT in ) { int x, y; int pick = -1; float big = ( float ) 9999999.0f; for( x = 0; x < Dtotalfaces; x++ ) { float d, dx, dy, dz; VERT c; float ii; c.x = 0; c.y = 0; c.z = 0; for( y = Dface_start[x]; y < Dface_end[x]; y++ ) { int g; g = Dfacelist[y]; c.x += Dv[g].x; c.y += Dv[g].y; c.z += Dv[g].z; } ii = Dface_end[x] - Dface_start[x]; if( ii > 0 ) { c.x /= ii; c.y /= ii; c.z /= ii; } dx = in.x - c.x; dx *= dx; dy = in.y - c.y; dy *= dy; dz = in.z - c.z; dz *= dz; d = dx + dy + dz; d = fsqrt( d ); if( d < big ) { pick = x; big = d; } } // pick=2; return ( pick ); } static int find_closest_vert( VERT in ) { int x; int pick = -1; float big = ( float ) 9999999.0f; for( x = 0; x < Dtotalverts; x++ ) { float d, dx, dy, dz; VERT c; c.x = 0; c.y = 0; c.z = 0; c = Dv[x]; dx = in.x - c.x; dx *= dx; dy = in.y - c.y; dy *= dy; dz = in.z - c.z; dz *= dz; d = dx + dy + dz; d = fsqrt( d ); if( d < big ) { pick = x; big = d; } } // pick=2; return ( pick ); } static void lock_verts( void ) { int x; int y; for( x = 0; x < totalverts; x++ ) { for( y = 1; y < 15; y++ ) { if( hair[x].select[y] ) if( hair[x].hide != 1 ) { hair[x].pfID[y] = find_closest_poly( hair[x].hv[y] ); // hair[x].pfID[y]=hair[x].pfID[y]; } } // resthair[x]=hair[x]; } for( x = 0; x < total_splines; x++ ) { for( y = 1; y < 15; y++ ) { if( Shair[x].select[y] ) if( Shair[x].hide != 1 ) { Shair[x].pfID[y] = find_closest_poly( Shair[x].hv[y] ); Sresthair[x].pfID[y] = Shair[x].pfID[y]; } } Sresthair[x] = Shair[x]; } } static void unlock_verts( void ) { int x; int y; for( x = 0; x < totalverts; x++ ) { for( y = 0; y < 15; y++ ) { if( hair[x].select[y] ) if( hair[x].hide != 1 ) { hair[x].pfID[y] = -1; // resthair[x].pfID[y]= -1; } } } for( x = 0; x < total_splines; x++ ) { for( y = 0; y < 15; y++ ) { if( Shair[x].select[y] ) if( Shair[x].hide != 1 ) { Shair[x].pfID[y] = -1; Sresthair[x].pfID[y] = -1; } } } } /* animation info */ static int total_channels = 0; //#include "savebuff.c" //#include "mathstuff.c" //#include "vector_stuff.c" //#include "gl_joe.c" //#include "audio.c" //#include "gui.c" #include "mod_mush.c" #include "fileio.c" #include "performance.c" //#include "MatrixInvert.c" #include "sculpt.c" //#include "cloth_equiv.c" //#include "subdiv.c" static int Jexists( void *fname ) { FILE *fp = NULL; int ret = 0; int trys = 0; if( RW_CONTEXT == RW_DISK ) { fp = MYfopen( ( CHNG * ) fname, _T("rb") ); if( fp ) ret = 1; // while ((ret==0)&&(trys<10)) // { // printf ("didn't find %s, try #%d\n",(char *)fname,trys); // fp=fopen((char *)fname,"rb"); // if (fp!=NULL) ret=1; // Sleep(2500); // trys++; // } if( ret > 0 ) fclose( fp ); } if( RW_CONTEXT == RW_LOCAL ) { fname = ( MEMFILE * ) fname; if( fname ) ret = 1; else ret = 0; } return ( ret ); } static int JexistsNOWAIT( void *fname ) { FILE *fp = NULL; int ret = 0; int trys = 0; if( RW_CONTEXT == RW_DISK ) { fp = MYfopen( ( CHNG * ) fname, _T("rb") ); if( fp ) ret = 1; while( ( ret == 0 ) && ( trys < 2 ) ) { printf( "didn't find %s, try #%d\n", ( char * ) fname, trys ); fp = MYfopen( ( CHNG * ) fname, _T("rb") ); if( fp != NULL ) ret = 1; #ifndef _MAC Sleep( 2 ); #endif trys++; } // if (fp== -1) ret=0; if( ret > 0 ) fclose( fp ); } if( RW_CONTEXT == RW_LOCAL ) { fname = ( MEMFILE * ) fname; if( fname ) ret = 1; else ret = 0; } return ( ret ); } static float distance( VERT a, VERT b ); static void make_inst( int slg, int aa ) { RENDERHAIR base, hx; BASEHAIR tmph; VERT Cxv; VERT offs; CURVEINFO cinf; // VERT xv; int y; offs.x = 0; offs.y = 0; offs.z = 0; hairID = ( aa ); GhairID=aa; hairID = aa; slgID = slg; // tmph = ( draw_lotsWF2( slg, aa, offs ) ); draw_lotsWF( slg, aa, offs,0,&tmph,&cinf ) ; matrixhair.norm = tmph.norm; matrixhair.killme = tmph.killme; { CURVEINFO cinfo; int xx; WFTYPE geom; init_geomWF( &geom ); resize_base_hair( &tmph, &geom, &cinfo, 56 ); for( xx = 0; xx < geom.totalverts; xx++ ) { base.hv[xx] = geom.v[xx]; base.velocity[xx] = geom.velocity[xx]; base.color[xx] = geom.color[xx]; } free_geomWF( &geom ); matrixhair.pid = tmph.pid; } // resample(tmph,&base); // base=cut_single_hair(base); offs.x = 1.0f; offs.y = 0; offs.z = 0; matrixhair.killme = tmph.killme; if( tmph.killme == 0 ) { draw_lotsWF2( slg, aa, offs,0,&tmph,&cinf ) ; // resample(tmph,&hx); { CURVEINFO cinfo; int xx; WFTYPE geom; init_geomWF( &geom ); resize_base_hair( &tmph, &geom, &cinfo, 56 ); for( xx = 0; xx < geom.totalverts; xx++ ) { hx.hv[xx] = geom.v[xx]; } free_geomWF( &geom ); matrixhair.pid = tmph.pid; Cxv=tmph.handle; } // hx=cut_single_hair(hx); offs.x = 0; // Cxv.x = hx.hv[0].x - base.hv[0].x; // Cxv.y = hx.hv[0].y - base.hv[0].y; // Cxv.z = hx.hv[0].z - base.hv[0].z; Cxv = Vnorm( Cxv ); for( y = 0; y < 56; y++ ) { VERT xv, yv, zv, yv2; int y1, y2; int y3, y4; y1 = y; y2 = y + 1; y3 = y1 + 1; y4 = y2 + 1; if( y1 >= 56 ) { y2--; y1--; } if( y1 >= 56 ) { y2--; y1--; } if( y3 >= 56 ) { y3--; y4--; } if( y3 >= 56 ) { y3--; y4--; } //rest2zero this is the first up vector yv.x = base.hv[y2].x - base.hv[y1].x; yv.y = base.hv[y2].y - base.hv[y1].y; yv.z = base.hv[y2].z - base.hv[y1].z; yv2.x = base.hv[y4].x - base.hv[y3].x; yv2.y = base.hv[y4].y - base.hv[y3].y; yv2.z = base.hv[y4].z - base.hv[y3].z; yv = Vnorm( yv ); yv2 = Vnorm( yv2 ); yv.x = ( yv.x + yv2.x ) / 2.0f; yv.y = ( yv.y + yv2.y ) / 2.0f; yv.z = ( yv.z + yv2.z ) / 2.0f; yv = Vnorm( yv ); // this is the plane normal // project Cxv onto the plane zv = Vcross( Cxv, yv ); zv = Vnorm( zv ); Cxv = Vcross( yv, zv ); Cxv = Vnorm( Cxv ); mkmatrix2( matrixhair.zero2world[y], Cxv, yv, zv, offs ); matrixhair.mtl = tmph.slgroup; matrixhair.dreadroot = tmph.dreadroot; matrixhair.dreadtip = tmph.dreadtip; // matrixhair.pid=base.pid; matrixhair.vid = aa; matrixhair.dreadcount = tmph.dreadcount; matrixhair.diffuse = tmph.diffuse; if( matrixhair.diffuse > 1.0 ) matrixhair.diffuse = 1.0f; ; matrixhair.spec = tmph.spec; matrixhair.kspec = tmph.kspec; matrixhair.ambient = tmph.ambient; // matrixhair.ambient= 1.0f; // come back matrixhair.rootfrizz = tmph.rootfrizz; matrixhair.tipfrizz = tmph.tipfrizz; matrixhair.clumpfreq = tmph.clumpfreq; matrixhair.kink = tmph.kink; matrixhair.kinkfreq = tmph.kinkfreq; // matrixhair.thickness=base.thickness; base.uu = 0.0f; base.vv = 0.0f; matrixhair.uu = base.uu; matrixhair.vv = base.vv; // matrixhair.norm=base.norm; matrixhair.cutlength = tmph.cutlength; matrixhair.thickness = tmph.thickness * tmph.slider[20]; matrixhair.thicknesstip = tmph.thicknesstip * tmph.slider[37]; matrixhair.hairnumber = aa; matrixhair.worldpos[y] = base.hv[y]; matrixhair.velocity[y] = base.velocity[y]; matrixhair.color[y].x = base.color[y].x; matrixhair.color[y].y = base.color[y].y; matrixhair.color[y].z = base.color[y].z; matrixhair.slg = tmph.slgroup; } //memcpy(&matrixhair.zero2world[54],&matrixhair.zero2world[53],sizeof(Matrix)); //memcpy(&matrixhair.zero2world[55],&matrixhair.zero2world[54],sizeof(Matrix)); //memcpy(&matrixhair.zero2world[56],&matrixhair.zero2world[55],sizeof(Matrix)); //#endif matrixhair.restlength = distance( base.hv[12], base.hv[11] ); // matrixhair.restlength=tmph.restlength*(15.0/56.0); } } #include "math.h" static void Imake_normals( void ) { int x, f, q; q = 0; for( x = 0; x < freeze.totalverts; x++ ) { freezetmp.vn[x].x = 0.0f; freezetmp.vn[x].y = 0.0f; freezetmp.vn[x].z = 0.0f; } for( f = 0; f < freeze.totalfaces; f++ ) // if ((freeze.face_end[f]-freeze.face_start[f])>=3) { VERT v1, v2, v3; VERT uu, vv, cross; int x; x = freeze.face_start[f]; v1 = freezetmp.v[freeze.facelist[x + 2]]; v2 = freezetmp.v[freeze.facelist[x + 1]]; v3 = freezetmp.v[freeze.facelist[x + 0]]; 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; cross = Vcross( uu, vv ); v1.x = cross.x; v1.y = cross.y; v1.z = cross.z; for( x = freeze.face_start[f]; x < freeze.face_end[f]; x++ ) { freezetmp.vn[freeze.facelist[x]].x += v1.x; freezetmp.vn[freeze.facelist[x]].y += v1.y; freezetmp.vn[freeze.facelist[x]].z += v1.z; } } for( x = 0; x < freeze.totalverts; x++ ) { float a, b, c, d; a = freezetmp.vn[x].x; b = freezetmp.vn[x].y; c = freezetmp.vn[x].z; d = fsqrt( a * a + b * b + c * c ); if( d != 0.0 ) { a = a / d; b = b / d; c = c / d; } else { a += ( float ) .00001; } freezetmp.vn[x].x = a; freezetmp.vn[x].y = b; freezetmp.vn[x].z = c; //#ifdef wavefront // vn[x].x = -vn[x].x; // vn[x].y = -vn[x].y; // vn[x].z = -vn[x].z; //#endif } // relight(); } static void make_normalsWF( WFTYPE * wf ) { int x, f, q; q = 0; for( x = 0; x < wf->totalverts; x++ ) { wf->vn[x].x = 0.0f; wf->vn[x].y = 0.0f; wf->vn[x].z = 0.0f; } for( f = 0; f < wf->totalfaces; f++ ) if( ( wf->face_end[f] - wf->face_start[f] ) >= 3 ) { VERT v1, v2, v3; VERT uu, vv, cross; int x; x = wf->face_start[f]; v1 = wf->v[wf->facelist[x + 2]]; v2 = wf->v[wf->facelist[x + 1]]; v3 = wf->v[wf->facelist[x + 0]]; 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 = Vcross( uu, vv ); v1.x = cross.x; v1.y = cross.y; v1.z = cross.z; v1 = Vnorm( v1 ); for( x = wf->face_start[f]; x < wf->face_end[f]; x++ ) { wf->vn[wf->facelist[x]].x += v1.x; wf->vn[wf->facelist[x]].y += v1.y; wf->vn[wf->facelist[x]].z += v1.z; } } for( x = 0; x < wf->totalverts; x++ ) { float a, b, c, d; a = wf->vn[x].x; b = wf->vn[x].y; c = wf->vn[x].z; d = fsqrt( a * a + b * b + c * c ); if( d != 0.0 ) { a = a / d; b = b / d; c = c / d; } else { a += ( float ) .00001; } wf->vn[x].x = a; wf->vn[x].y = b; wf->vn[x].z = c; //#ifdef wavefront // vn[x].x = -vn[x].x; // vn[x].y = -vn[x].y; // vn[x].z = -vn[x].z; //#endif // wf->vn[x]=Vnorm(wf->vn[x]); } // relight(); } static void make_normalsHT( HAIRTYPE * wf, VERT *vvn ) { int x, f, q; q = 0; for( x = 0; x < wf->totalverts; x++ ) { vvn[x].x = 0.0f; vvn[x].y = 0.0f; vvn[x].z = 0.0f; } for( f = 0; f < wf->totalfaces; f++ ) if( ( wf->face_end[f] - wf->face_start[f] ) >= 3 ) { VERT v1, v2, v3; VERT uu, vv, cross; int x; x = wf->face_start[f]; v1 = wf->v[wf->facelist[x + 2]]; v2 = wf->v[wf->facelist[x + 1]]; v3 = wf->v[wf->facelist[x + 0]]; 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 = Vcross( uu, vv ); v1.x = cross.x; v1.y = cross.y; v1.z = cross.z; v1 = Vnorm( v1 ); for( x = wf->face_start[f]; x < wf->face_end[f]; x++ ) { vvn[wf->facelist[x]].x += v1.x; vvn[wf->facelist[x]].y += v1.y; vvn[wf->facelist[x]].z += v1.z; } } for( x = 0; x < wf->totalverts; x++ ) { float a, b, c, d; a = vvn[x].x; b = vvn[x].y; c = vvn[x].z; d = fsqrt( a * a + b * b + c * c ); if( d != 0.0 ) { a = a / d; b = b / d; c = c / d; } else { a += ( float ) .00001; } vvn[x].x = a; vvn[x].y = b; vvn[x].z = c; //#ifdef wavefront // vn[x].x = -vn[x].x; // vn[x].y = -vn[x].y; // vn[x].z = -vn[x].z; //#endif // wf->vn[x]=Vnorm(wf->vn[x]); } // relight(); } static void Irelight( void ) { int x; VERT lg1; VERT vvn; Imake_normals( ); // getmatrix(CamMatrix); // inverse( CamMatrix, InvCamMatrix ); lg1.x = ( float ) 5.3333; lg1.y = ( float ) .3333; lg1.z = ( float ) 10.3333; // lg=Vnorm(lgworld); // lg=vxm(CamMatrix,lg); lg1 = Vnorm( lg1 ); // map_colors(); for( x = 0; x < freeze.totalfaces; x++ ) { int y; for( y = freeze.face_start[x]; y < freeze.face_end[x]; y++ ) { int g; g = freeze.facelist[y]; // restore locked color freezetmp1.Rrvcolor[g] = freezetmp.Rrvcolor[g]; freezetmp1.Rgvcolor[g] = freezetmp.Rgvcolor[g]; freezetmp1.Rbvcolor[g] = freezetmp.Rbvcolor[g]; // sprintf (tmp,"freeze %d = %f %f %f",g,freeze.Rrvcolor[g],freeze.Rgvcolor[g],freeze.Rbvcolor[g]); // DRAW_STATUS(tmp); } } for( x = 0; x < freeze.totalverts; x++ ) { // shading float spec; VERT H; float shd; vvn = freezetmp.vn[x]; shd = vvn.x * lg1.x + vvn.y * lg1.y + vvn.z * lg1.z; if( shd < 0 ) shd = 0; shd *= matrixhair.diffuse; shd += ( 1.0f - matrixhair.diffuse ); H.x = ( 0.0 + lg1.x ) / 2.0f; H.y = ( 0.0 + lg1.y ) / 2.0f; H.z = ( -1.0 + lg1.z ) / 2.0f; H = Vnorm( H ); spec = dot( vvn, H ); if( spec < 0 ) spec = -spec; if( matrixhair.kspec > 0.0 ) spec = pow( spec, 1.0 / ( 3.0 * ( .101 - matrixhair.kspec ) ) ); if( spec > 1.0 ) spec = 1.0f; if( spec < 0.0 ) spec = 0.0f; spec *= matrixhair.spec; spec *= 255; if( shd > 1 ) shd = 1; freezetmp.rvcolor[x] = ( shd * ( float ) freezetmp1.Rrvcolor[x] ) + spec; freezetmp.gvcolor[x] = ( shd * ( float ) freezetmp1.Rgvcolor[x] ) + spec; freezetmp.bvcolor[x] = ( shd * ( float ) freezetmp1.Rbvcolor[x] ) + spec; } } static void LWIrelight( void ) { int x; VERT lg1; int ll = 0; VERT vvn; // getmatrix(CamMatrix); // inverse( CamMatrix, InvCamMatrix ); WFTYPE ins; init_geomWF( &ins ); ins.totalverts = freeze.totalverts; ins.totalfaces = freeze.totalfaces; ins.totalfverts = freeze.totalfverts; alloc_geomWF( &ins ); for( x = 0; x < freeze.totalfverts; x++ ) ins.facelist[x] = freeze.facelist[x]; for( x = 0; x > freeze.totalfaces; x++ ) { ins.face_start[x] = freeze.face_start[x]; ins.face_end[x] = ins.face_end[x]; } Imake_normals( ); for( x = 0; x < freeze.totalfaces; x++ ) { int y; if( freeze.colorlock[x] >= 0 ) for( y = freeze.face_start[x]; y < freeze.face_end[x]; y++ ) { { int g; g = freeze.facelist[y]; // restore locked color freezetmp.Rrvcolor[g] = freeze.Rrvcolor[g]; freezetmp.Rgvcolor[g] = freeze.Rgvcolor[g]; freezetmp.Rbvcolor[g] = freeze.Rbvcolor[g]; } } } for( x = 0; x < freeze.totalverts; x++ ) { ins.color[x].x = freezetmp.Rrvcolor[x]; ///255.0f; ins.color[x].y = freezetmp.Rgvcolor[x]; ///255.0f; ins.color[x].z = freezetmp.Rbvcolor[x]; ///255.0f; ins.v[x] = freezetmp.v[x]; } SHAVEapply_inst_color( &ins, hairID, slgID, SHAVEID ); for( x = 0; x < freeze.totalverts; x++ ) { freezetmp.v[x] = ins.v[x]; // ins.color[x].x*=255.0f; is this right??? // ins.color[x].y*=255.0f; // ins.color[x].z*=255.0f; freeze.Rrvcolor[x] = ins.color[x].x; freeze.Rgvcolor[x] = ins.color[x].y; freeze.Rbvcolor[x] = ins.color[x].z; freezetmp.Rrvcolor[x] = ins.color[x].x; freezetmp.Rgvcolor[x] = ins.color[x].y; freezetmp.Rbvcolor[x] = ins.color[x].z; freezetmp1.Rrvcolor[x] = ins.color[x].x; freezetmp1.Rgvcolor[x] = ins.color[x].y; freezetmp2.Rbvcolor[x] = ins.color[x].z; freezetmp2.Rrvcolor[x] = ins.color[x].x; freezetmp2.Rgvcolor[x] = ins.color[x].y; freezetmp2.Rbvcolor[x] = ins.color[x].z; } free_geomWF( &ins ); for( x = 0; x < freeze.totalverts; x++ ) { freezetmp.rvcolor[x] = 0; freezetmp.gvcolor[x] = 0; freezetmp.bvcolor[x] = 0; } for( ll = 0; ll < totallights; ll++ ) if( LWlight[ll].xres > 0 ) if( LWlight[ll].radiosity == 0 ) if( LWlight[ll].caustics == 0 ) { double tmpp[3], tmpd[3], tmpc[3]; for( x = 0; x < freeze.totalverts; x++ ) { // shading float spec; VERT eye, H; float shd; // int jk; VERT lum, lum2; tmpp[0] = freezetmp.v[x].x; tmpp[1] = freezetmp.v[x].y; tmpp[2] = freezetmp.v[x].z; #ifdef RENDERLW #ifndef VOLUMETRICLW // jk=(*Gsa->illuminate)(LWlight[ll].id,tmpp,tmpd,tmpc); #endif #ifdef VOLUMETRICLW // jk=(*VGsa->illuminate)(LWlight[ll].id,tmpp,tmpd,tmpc); #endif #endif ////#ifndef RENDERLW { VERT tpos, tcol; tpos.x = tmpp[0]; tpos.y = tmpp[1]; tpos.z = tmpp[2]; tcol = Gilluminate( tpos, ll, matrixhair.ambient ); tmpc[0] = tcol.x; tmpc[1] = tcol.y; tmpc[2] = tcol.z; } ///#endif /////tmpc[0]=1; ////tmpc[1]=1; ///tmpc[2]=1; // hack tmpd[0] = LWlight[ll].wpos.x - ( float ) tmpp[0]; tmpd[1] = LWlight[ll].wpos.y - ( float ) tmpp[1]; tmpd[2] = LWlight[ll].wpos.z - ( float ) tmpp[2]; // jk=Gsa->illuminate(LWlight[ll].id,tmpp,tmpd,tmpc); lg1.x = ( float ) tmpd[0]; lg1.y = ( float ) tmpd[1]; lg1.z = ( float ) tmpd[2]; lg1 = Vnorm( lg1 ); lum.x = tmpc[0]; lum.y = tmpc[1]; lum.z = tmpc[2]; //lum.x=1.0f; //lum.y=1.0f; //lum.z=1.0f; lum2.x = 0; lum2.y = 0; lum2.z = 0; { // int ii; //for (ii=0;ii<3;ii++) { // VERT tlm; //tlm=cast_shadows_lgt(freezetmp.v[x],ll); //lum2.x+=tlm.x/3.0f; //lum2.y+=tlm.y/3.0f; //lum2.z+=tlm.z/3.0f; } } lum2.x = 1.0f; lum2.y = 1.0f; lum2.z = 1.0f; lum.x *= lum2.x; lum.y *= lum2.y; lum.z *= lum2.z; eye.x = LWlight[ll].wpos.x - freezetmp.v[x].x; eye.y = LWlight[ll].wpos.y - freezetmp.v[x].y; eye.z = LWlight[ll].wpos.z - freezetmp.v[x].z; vvn = freezetmp.vn[x]; vvn.x = vvn.x; vvn.y = vvn.y; vvn.z = vvn.z; shd = vvn.x * lg1.x + vvn.y * lg1.y + vvn.z * lg1.z; if( shd < 0 ) shd = 0; shd *= matrixhair.diffuse; shd += ( 1.0f - matrixhair.diffuse ); // shd*=(matrixhair.ambient); // shd+=(1.0f-matrixhair.ambient); H.x = ( eye.x + lg1.x ) / 2.0f; H.y = ( eye.y + lg1.y ) / 2.0f; H.z = ( eye.z + lg1.z ) / 2.0f; H = Vnorm( H ); spec = dot( vvn, H ); if( spec < 0 ) spec = -spec; if( matrixhair.kspec > 0.0 ) spec = pow( spec, 1.0 / ( 3.0 * ( .101 - matrixhair.kspec ) ) ); // if (spec>1.0) spec=1.0f; if( spec < 0.0 ) spec = 0.0f; spec *= matrixhair.spec; spec *= 255; if( shd < ( ambient[0] + ambient[1] + ambient[2] ) / 3.0 ) shd = ( ambient[0] + ambient[1] + ambient[2] ) / 3.0f; if( shd > 1 ) shd = 1; freezetmp.rvcolor[x] += ( ( shd * ( float ) freezetmp.Rrvcolor[x] ) + spec ) * lum.x; freezetmp.gvcolor[x] += ( ( shd * ( float ) freezetmp.Rgvcolor[x] ) + spec ) * lum.y; freezetmp.bvcolor[x] += ( ( shd * ( float ) freezetmp.Rbvcolor[x] ) + spec ) * lum.z; if( freezetmp.rvcolor[x] > 255 ) freezetmp.rvcolor[x] = 255; if( freezetmp.gvcolor[x] > 255 ) freezetmp.gvcolor[x] = 255; if( freezetmp.bvcolor[x] > 255 ) freezetmp.bvcolor[x] = 255; if( freezetmp.rvcolor[x] < 0 ) freezetmp.rvcolor[x] = 0; if( freezetmp.gvcolor[x] < 0 ) freezetmp.gvcolor[x] = 0; if( freezetmp.bvcolor[x] < 0 ) freezetmp.bvcolor[x] = 0; // freezetmp.rvcolor[x]+=((shd*(float)freezetmp.Rrvcolor[x])+spec)*(float)tmpc[0]; // freezetmp.gvcolor[x]+=((shd*(float)freezetmp.Rgvcolor[x])+spec)*(float)tmpc[1]; // freezetmp.bvcolor[x]+=((shd*(float)freezetmp.Rbvcolor[x])+spec)*(float)tmpc[2]; // freezetmp.rvcolor[x]+=((ambient[0]*(float)freezetmp.Rrvcolor[x])+spec); // freezetmp.gvcolor[x]+=((ambient[1]*(float)freezetmp.Rgvcolor[x])+spec); // freezetmp.bvcolor[x]+=((ambient[2]*(float)freezetmp.Rbvcolor[x])+spec); } } for( x = 0; x < freeze.totalverts; x++ ) { VERT tmpv, tmpc; tmpv = freezetmp.v[x]; tmpc.x = freezetmp.rvcolor[x]; tmpc.y = freezetmp.gvcolor[x]; tmpc.z = freezetmp.bvcolor[x]; tmpc.x /= 255.0f; tmpc.y /= 255.0f; tmpc.z /= 255.0f; tmpv.z = -tmpv.z; SHAVEcoord_convertFROMSHAVE( &tmpv ); tmpc = SHAVEapply_atmosphere( tmpv, tmpc ); // SHAVEcoord_convertTOSHAVE(&tmpv); tmpc.x *= 255.0f; tmpc.y *= 255.0f; tmpc.z *= 255.0f; if( tmpc.x > 255.0f ) tmpc.x = 255.0f; if( tmpc.y > 255.0f ) tmpc.y = 255.0f; if( tmpc.z > 255.0f ) tmpc.z = 255.0f; if( tmpc.x < 0.0f ) tmpc.x = 0.0f; if( tmpc.y < 0.0f ) tmpc.y = 0.0f; if( tmpc.z < 0.0f ) tmpc.z = 0.0f; freezetmp.rvcolor[x] = tmpc.x; freezetmp.gvcolor[x] = tmpc.y; freezetmp.bvcolor[x] = tmpc.z; } } static void WFIrelight( WFTYPE * wf ) { int x; VERT lg1; int ll = 0; float bb; VERT vvn; WFTYPE *shadowobj; shadowobj = ( WFTYPE * ) malloc( totallights * sizeof( WFTYPE ) ); for( ll = 0; ll < totallights; ll++ ) init_geomWF( &shadowobj[ll] ); make_normalsWF( wf ); bb = restBOUNDLENGTH / 700.0f; for( ll = 0; ll < totallights; ll++ ) { shadowobj[ll].totalverts = wf->totalverts + 10; shadowobj[ll].totalfaces = wf->totalfaces + 10; shadowobj[ll].totalfverts = wf->totalfverts + 10; } for( ll = 0; ll < totallights; ll++ ) alloc_geomWF( &shadowobj[ll] ); for( ll = 0; ll < totallights; ll++ ) { for( x = 0; x < wf->totalverts; x++ ) { VERT pp; shadowobj[ll].v[x] = wf->v[x]; shadowobj[ll].v[x].z *= -1; shadowobj[ll].color[x].x = 1.0f; shadowobj[ll].color[x].y = 1.0f; shadowobj[ll].color[x].z = 1.0f; shadowobj[ll].velocity[x].x = 0.0f; shadowobj[ll].velocity[x].y = 0.0f; shadowobj[ll].velocity[x].z = 0.0f; SHAVEcoord_convertFROMSHAVE( &shadowobj[ll].v[x] ); // shadowobj[ll].v[x]=Gilluminate(pp,ll,matrixhair.ambient); } Gilluminate_strandINST( &shadowobj[ll], ll, matrixhair.ambient ); } //mknorms_geom(&wf); for( x = 0; x < wf->totalverts; x++ ) { VERT l, il, lll; VERT in; il.x = 0; il.y = 0; il.z = 0; in = wf->v[x]; // SHAVEcoord_convertFROMSHAVE(&in); for( ll = 0; ll < totallights; ll++ ) { float l = 0.0f; int xxx; VERT pp; VERT lqq; VERT eye, H, vvn, ld; float shd = 0; float spec = 0.0f; pp = wf->v[x]; lll = shadowobj[ll].color[x]; if( LWlight[ll].xres == 0 ) { lll.x = 1.0f; lll.y = 1.0f; lll.z = 1.0f; } ld = find_vector( pp, LWlight[ll].wpos ); ld = Vnorm( ld ); // light vector eye.x = LWcam.wpos.x - pp.x; // cam vector eye.y = LWcam.wpos.y - pp.y; eye.z = LWcam.wpos.z - pp.z; eye = Vnorm( eye ); vvn = wf->vn[x]; vvn = Vnorm( vvn ); shd = vvn.x * ld.x + vvn.y * ld.y + vvn.z * ld.z; shd *= -1; // don't think I want to flip the normal either shd *= matrixhair.diffuse; if( shd < 0 ) shd = 0; if( shd > 1.0 ) shd = 1.0f; shd += ( 1.0f - matrixhair.diffuse ); if( shd < 0 ) shd = 0; if( shd > 1.0 ) shd = 1.0f; H.x = ( eye.x + ld.x ) / 2.0f; H.y = ( eye.y + ld.y ) / 2.0f; H.z = ( eye.z + ld.z ) / 2.0f; H = Vnorm( H ); H.x = H.x; H.y = H.y; H.z = H.z; spec = dot( vvn, H ); if( spec < 0 ) spec = -spec; if( spec > 1 ) spec = 1; if( matrixhair.kspec > 0.0 ) spec = pow( spec, 1.0 / ( 3.0 * ( .101 - matrixhair.kspec ) ) ); spec *= matrixhair.spec; if( spec < 0.0 ) spec = 0.0f; if( spec > 1.0 ) spec = 1.0f; // spec*=255.0f; shd *= matrixhair.ambient + ( 1.0f - matrixhair.ambient ); if( shd > 1.0f ) shd = 1.0f; if( shd < 0.0f ) shd = 1.0f; lll.x /= 255.0f; lll.y /= 255.0f; lll.z /= 255.0f; // shd=1; // spec=0; il.x += ( lll.x * wf->color[x].x * shd + lll.x * spec * 255.0f ); il.y += ( lll.y * wf->color[x].y * shd + lll.y * spec * 255.0f ); il.z += ( lll.z * wf->color[x].z * shd + lll.z * spec * 255.0f ); } wf->color[x].x = il.x; wf->color[x].y = il.y; wf->color[x].z = il.z; //lets see the raw color if( wf->color[x].x > 255.0f ) wf->color[x].x = 255.0f; if( wf->color[x].y > 255.0f ) wf->color[x].y = 255.0f; if( wf->color[x].z > 255.0f ) wf->color[x].z = 255.0f; if( wf->color[x].x < 0.0f ) wf->color[x].x = 0.0f; if( wf->color[x].y < 0.0f ) wf->color[x].y = 0.0f; if( wf->color[x].z < 0.0f ) wf->color[x].z = 0.0f; } for( ll = 0; ll < totallights; ll++ ) free_geomWF( &shadowobj[ll] ); free( shadowobj ); } static void metanurbfixINST( void ) { } static void metanurbfix( RENDERHAIR * hh ) { // return(hh); } //#ifdef LIB static void LWdraw_lotsINST( void ) { int x; int hc2 = 0; int cs; int slg; reset_faces( ); checkforzero( ); mkbounds( ); weight_polys( ); texture_bounds( ); cs = ( Gcurpass + 1 ) % MAXPASSES; //for (x=0;x0) hc2++; for( x = 0; x < 5; x++ ) if( total_slgfaces[x] > 0 ) hc2++; if( hc2 > 0 ) for( slg = 0; slg < 5; slg++ ) if( total_slgfaces[slg] > 0 ) for( x = 0; x < LOCAL_CNT[slg]; x++ ) { int xx; POLYDAT tri; make_inst( slg, x ); if( matrixhair.dreadcount == 0 ) { xforminst( 0 ); cs = ( Gcurpass + 1 ) % LOCAL_PASSES[slg]; //// if (cs==(LOCAL_PASSES[slg]-1)) cs=0; if( Graycast ) { metanurbfixINST( ); } if( itsalight == 0 ) LWIrelight( ); if( freeze.totalverts > 0 ) for( xx = 0; xx < freeze.totalfaces; xx++ ) { int g; g = freeze.facelist[freeze.face_start[xx]]; tri.p[0] = freezetmp.v[g]; tri.v[0] = freezetmp.velocity[g]; tri.c[0].x = freezetmp.rvcolor[g]; tri.c[0].y = freezetmp.gvcolor[g]; tri.c[0].z = freezetmp.bvcolor[g]; g = freeze.facelist[freeze.face_start[xx] + 1]; tri.p[1] = freezetmp.v[g]; tri.v[1] = freezetmp.velocity[g]; tri.c[1].x = freezetmp.rvcolor[g]; tri.c[1].y = freezetmp.gvcolor[g]; tri.c[1].z = freezetmp.bvcolor[g]; g = freeze.facelist[freeze.face_start[xx] + 2]; tri.p[2] = freezetmp.v[g]; tri.v[2] = freezetmp.velocity[g]; tri.c[2].x = freezetmp.rvcolor[g]; tri.c[2].y = freezetmp.gvcolor[g]; tri.c[2].z = freezetmp.bvcolor[g]; draw_poly3d( tri, cs, ( unsigned char ) ( matrixhair.ambient * 255.0 ) ); // come back } } // dreadcount if( matrixhair.dreadcount > 0 ) for( xx = 0; xx < matrixhair.dreadcount; xx++ ) { xforminst( xx ); cs = ( Gcurpass + 1 ) % LOCAL_PASSES[slg]; if( Graycast ) { metanurbfixINST( ); } if( itsalight == 0 ) LWIrelight( ); if( freeze.totalverts > 0 ) for( xx = 0; xx < freeze.totalfaces; xx++ ) { int g; g = freeze.facelist[freeze.face_start[xx]]; tri.p[0] = freezetmp.v[g]; tri.c[0].x = freezetmp.rvcolor[g]; tri.c[0].y = freezetmp.gvcolor[g]; tri.c[0].z = freezetmp.bvcolor[g]; g = freeze.facelist[freeze.face_start[xx] + 1]; tri.p[1] = freezetmp.v[g]; tri.c[1].x = freezetmp.rvcolor[g]; tri.c[1].y = freezetmp.gvcolor[g]; tri.c[1].z = freezetmp.bvcolor[g]; g = freeze.facelist[freeze.face_start[xx] + 2]; tri.p[2] = freezetmp.v[g]; tri.c[2].x = freezetmp.rvcolor[g]; tri.c[2].y = freezetmp.gvcolor[g]; tri.c[2].z = freezetmp.bvcolor[g]; draw_poly3d( tri, cs, ( unsigned char ) ( matrixhair.ambient * 255.0 ) ); // come back } } // dreadcount>0 } } //#endif static int WFdraw_lotsINSTWD( WFTYPE * wf, int cs ) { int x; int ret; int hc2 = 0; int success = 0; int succ = 0; POLYDAT tri; int xx, yy; int md; int triangles = 0; success = 0; md = itsalight; for( xx = 0; xx < wf->totalverts; xx++ ) { // wf->v[xx].z*= -1.0f; SHAVEcoord_convertTOSHAVE( &wf->v[xx] ); SHAVEcoord_convertTOSHAVE( &wf->vn[xx] ); } if( itsalight == 1 ) if( wf->totalverts > 0 ) { for( xx = 0; xx < wf->totalfaces; xx++ ) { int g; g = wf->facelist[wf->face_start[xx]]; tri.p[0] = wf->v[g]; tri.v[0] = wf->velocity[g]; tri.c[0].x = wf->color[g].x; tri.c[0].y = wf->color[g].y; tri.c[0].z = wf->color[g].z; g = wf->facelist[wf->face_start[xx] + 1]; tri.p[1] = wf->v[g]; tri.v[1] = wf->velocity[g]; tri.c[1].x = wf->color[g].x; tri.c[1].y = wf->color[g].y; tri.c[1].z = wf->color[g].z; g = wf->facelist[wf->face_start[xx] + 2]; tri.p[2] = wf->v[g]; tri.v[2] = wf->velocity[g]; tri.c[2].x = wf->color[g].x; tri.c[2].y = wf->color[g].y; tri.c[2].z = wf->color[g].z; // draw_poly3d(tri,cs,(unsigned char) (matrixhair.ambient*255.0)); // come back for( yy = 0; yy < totallights; yy++ ) if( LWlight[yy].xres > 0 ) { current_cam = &LWlight[yy]; Gclipx0 = 0; Gclipy0 = 0; Gclipx1 = LWlight[yy].xres; Gclipy1 = LWlight[yy].xres; draw_poly3d( tri, cs, ( unsigned char ) ( matrixhair.ambient * 255.0 ) ); // come back } } } succ = 0; #ifdef alttagging if( md == 3 ) if( wf->totalverts > 0 ) { int totalclip = 0; VERT bnd1, bnd2; VERT sq1, sq2; VERT cube[8]; bnd1.x = 100000.0f; bnd1.y = 100000.0f; bnd1.z = 100000.0f; bnd2.x = 100000.0f; bnd2.y = 100000.0f; bnd2.z = 100000.0f; sq1.x = 100000.0f; sq1.y = 100000.0f; sq1.z = 100000.0f; sq2.x = 100000.0f; sq2.y = 100000.0f; sq2.z = 100000.0f; for( xx = 0; xx < wf->totalverts; xx++ ) { if( wf->v[xx].x > bnd2.x ) bnd2.x = wf->v[xx].x; if( wf->v[xx].y > bnd2.y ) bnd2.y = wf->v[xx].y; if( wf->v[xx].z > bnd2.z ) bnd2.z = wf->v[xx].z; if( wf->v[xx].x < bnd1.x ) bnd1.x = wf->v[xx].x; if( wf->v[xx].y < bnd1.y ) bnd1.y = wf->v[xx].y; if( wf->v[xx].z < bnd1.z ) bnd1.z = wf->v[xx].z; } for( xx = 0; xx < wf->totalverts; xx++ ) { if( wf->v[xx].x + wf->velocity[xx].x > bnd2.x ) bnd2.x = wf->v[xx].x + wf->velocity[xx].x; if( wf->v[xx].y + wf->velocity[xx].y > bnd2.y ) bnd2.y = wf->v[xx].y + wf->velocity[xx].y; if( wf->v[xx].z + wf->velocity[xx].z > bnd2.z ) bnd2.z = wf->v[xx].z + wf->velocity[xx].z; if( wf->v[xx].x + wf->velocity[xx].x < bnd1.x ) bnd1.x = wf->v[xx].x + wf->velocity[xx].x; if( wf->v[xx].y + wf->velocity[xx].y < bnd1.y ) bnd1.y = wf->v[xx].y + wf->velocity[xx].y; if( wf->v[xx].z + wf->velocity[xx].z < bnd1.z ) bnd1.z = wf->v[xx].z + wf->velocity[xx].z; } cube[0].x = bnd1.x; cube[0].y = bnd1.y; cube[0].z = bnd1.z; cube[1].x = bnd1.x; cube[1].y = bnd1.y; cube[1].z = bnd2.z; cube[2].x = bnd2.x; cube[2].y = bnd1.y; cube[2].z = bnd2.z; cube[3].x = bnd2.x; cube[3].y = bnd1.y; cube[3].z = bnd1.z; cube[4].x = bnd1.x; cube[4].y = bnd2.y; cube[4].z = bnd1.z; cube[5].x = bnd1.x; cube[5].y = bnd2.y; cube[5].z = bnd2.z; cube[6].x = bnd2.x; cube[6].y = bnd2.y; cube[6].z = bnd2.z; cube[7].x = bnd2.x; cube[7].y = bnd2.y; cube[7].z = bnd1.z; for( xx = 0; xx < 8; xx++ ) { VERT2 gg; gg.x = cube[xx].x; gg.y = cube[xx].y; gg.z = cube[xx].z; gg = world2cam( &LWcam, gg ); totalclip += gg.clip; if( gg.x > sq2.x ) sq2.x = gg.x; if( gg.y > sq2.y ) sq2.y = gg.y; if( gg.z > sq2.z ) sq2.z = gg.z; if( gg.x < sq1.x ) sq1.x = gg.x; if( gg.y < sq1.y ) sq1.y = gg.y; if( gg.z < sq1.z ) sq1.z = gg.z; } if( sq1.x < 0 ) sq1.x = 0; if( sq1.y < 0 ) sq1.y = 0; if( sq2.x < 0 ) sq1.x = 0; if( sq2.y < 0 ) sq1.y = 0; if( sq1.x > LWcam.xres - 1 ) sq1.x = LWcam.xres - 1; if( sq1.y > LWcam.yres - 1 ) sq1.y = LWcam.yres - 1; if( sq2.x > LWcam.xres - 1 ) sq2.x = LWcam.xres - 1; if( sq2.y > LWcam.yres - 1 ) sq2.y = LWcam.yres - 1; if( totalclip < 8 ) for( xx = ( int ) sq1.x; xx < ( int ) sq2.x; xx++ ) for( yy = ( int ) sq1.y; yy < ( int ) sq2.y; yy++ ) { tag_tile( xx, yy, Gslg, GhairID, GnodeID,Gcurpass ); } } #endif if( ( md == 0 ) || ( md == 2 ) || ( md == 3 ) ) //if (succ>0) { int xx; if( TILEMODE < 6 ) current_cam = &LWcam; if( md == 0 ) if( TILEMODE == 6 ) if( wf->totalverts > 0 ) { for( xx = 0; xx < wf->totalverts; xx++ ) { SHAVEcoord_convertFROMSHAVE( &wf->v[xx] ); wf->vn[xx].z *= -1; SHAVEcoord_convertFROMSHAVE( &wf->vn[xx] ); } SHAVEapply_inst_color( wf, matrixhair.vid, matrixhair.slg, SHAVEID ); for( xx = 0; xx < wf->totalverts; xx++ ) { SHAVEcoord_convertTOSHAVE( &wf->v[xx] ); wf->vn[xx].z *= -1; SHAVEcoord_convertTOSHAVE( &wf->vn[xx] ); } } if( md == 0 ) if( TILEMODE == 6 ) { // for (xx=0;xxtotalverts;xx++) { // SHAVEcoord_convertFROMSHAVE(&wf->v[xx]); // wf->vn[xx].z*= -1; // SHAVEcoord_convertFROMSHAVE(&wf->vn[xx]); // wf->vn[xx].x*= -1; // wf->vn[xx].y*= -1; // wf->vn[xx].z*= -1; } // SHAVEapply_inst_color(wf, matrixhair.vid, matrixhair.slg,SHAVEID); WFIrelight( wf ); //lets look at this later // for (xx=0;xxtotalverts;xx++) { // wf->vn[xx].x*= -1; // wf->vn[xx].y*= -1; // wf->vn[xx].z*= -1; // SHAVEcoord_convertTOSHAVE(&wf->v[xx]); // wf->vn[xx].z*= -1; // SHAVEcoord_convertTOSHAVE(&wf->vn[xx]); } } if( TILEMODE == 6 ) if( wf->totalverts > 0 ) for( xx = 0; xx < wf->totalfaces; xx++ ) { int g; // itsalight=0; g = wf->facelist[wf->face_start[xx]]; tri.p[0] = wf->v[g]; tri.v[0] = wf->velocity[g]; tri.c[0].x = wf->color[g].x; tri.c[0].y = wf->color[g].y; tri.c[0].z = wf->color[g].z; //printf ("color = %f \n",wf->color[g].x); g = wf->facelist[wf->face_start[xx] + 1]; tri.p[1] = wf->v[g]; tri.v[1] = wf->velocity[g]; tri.c[1].x = wf->color[g].x; tri.c[1].y = wf->color[g].y; tri.c[1].z = wf->color[g].z; g = wf->facelist[wf->face_start[xx] + 2]; tri.p[2] = wf->v[g]; tri.v[2] = wf->velocity[g]; tri.c[2].x = wf->color[g].x; tri.c[2].y = wf->color[g].y; tri.c[2].z = wf->color[g].z; tri.p[3] = tri.p[0]; tri.c[3] = tri.c[0]; // if (success>0) // if (itsalight==0) if( TILEMODE == 6 ) { SHAVEcoord_convertFROMSHAVE( &tri.p[0] ); SHAVEcoord_convertFROMSHAVE( &tri.p[1] ); SHAVEcoord_convertFROMSHAVE( &tri.p[2] ); SHAVEcoord_convertFROMSHAVE( &tri.p[3] ); // tri.c[0].x=255.0f;tri.c[0].y=0.0f;tri.c[0].z=0.0f; // tri.c[1].x=255.0f;tri.c[1].y=0.0f;tri.c[1].z=0.0f; // tri.c[2].x=255.0f;tri.c[2].y=0.0f;tri.c[2].z=0.0f; // tri.c[3].x=255.0f;tri.c[3].y=0.0f;tri.c[3].z=0.0f; if( DOING_SWATCH == 0 ) { tri.c[0] = SHAVEapply_atmosphere( tri.p[0], tri.c[0] ); tri.c[1] = SHAVEapply_atmosphere( tri.p[1], tri.c[1] ); tri.c[2] = SHAVEapply_atmosphere( tri.p[2], tri.c[2] ); tri.c[3] = SHAVEapply_atmosphere( tri.p[3], tri.c[3] ); } SHAVEcoord_convertTOSHAVE( &tri.p[0] ); SHAVEcoord_convertTOSHAVE( &tri.p[1] ); SHAVEcoord_convertTOSHAVE( &tri.p[2] ); SHAVEcoord_convertTOSHAVE( &tri.p[3] ); //if (TILEMODE==0) current_cam= &LWcam; } draw_poly3d( tri, cs, ( unsigned char ) ( matrixhair.ambient * 255.0 ) ); // come back } if( itsalight != 1 ) if( TILEMODE != 6 ) // we're just tagging { VERT low, hi; int y; low.x = 999999; low.y = 999999; low.z = 999999; hi.x = -999999; hi.y = -999999; hi.z = -999999; if( wf->totalverts > 0 ) for( xx = 0; xx < wf->totalverts; xx++ ) { int g; // itsalight=0; // g=wf->facelist[wf->face_start[xx]]; g = xx; tri.p[0] = wf->v[g]; tri.v[0] = wf->velocity[g]; y = 0; { if( tri.p[y].x + tri.v[y].x < low.x ) low.x = tri.p[y].x + tri.v[y].x; if( tri.p[y].y + tri.v[y].y < low.y ) low.y = tri.p[y].y + tri.v[y].y; if( tri.p[y].z + tri.v[y].z < low.z ) low.z = tri.p[y].z + tri.v[y].z; if( tri.p[y].x + tri.v[y].x > hi.x ) hi.x = tri.p[y].x + tri.v[y].x; if( tri.p[y].y + tri.v[y].y > hi.y ) hi.y = tri.p[y].y + tri.v[y].y; if( tri.p[y].z + tri.v[y].z > hi.z ) hi.z = tri.p[y].z + tri.v[y].z; if( tri.p[y].x < low.x ) low.x = tri.p[y].x; if( tri.p[y].y < low.y ) low.y = tri.p[y].y; if( tri.p[y].z < low.z ) low.z = tri.p[y].z; if( tri.p[y].x > hi.x ) hi.x = tri.p[y].x; if( tri.p[y].y > hi.y ) hi.y = tri.p[y].y; if( tri.p[y].z > hi.z ) hi.z = tri.p[y].z; } } // ok, so we've got a 3d bound, but it really wants to be 2d // but for that we need all 8 points low.z *= -1; hi.z *= -1; SHAVEcoord_convertTOSHAVE( &low ); SHAVEcoord_convertTOSHAVE( &hi ); { VERT pp[8]; pp[0].x = low.x; pp[0].y = low.y; pp[0].z = low.z; pp[1].x = low.x; pp[1].y = low.y; pp[1].z = hi.z; pp[2].x = hi.x; pp[2].y = low.y; pp[2].z = hi.z; pp[3].x = hi.x; pp[3].y = low.y; pp[3].z = low.z; pp[4].x = low.x; pp[4].y = hi.y; pp[4].z = low.z; pp[5].x = low.x; pp[5].y = hi.y; pp[5].z = hi.z; pp[6].x = hi.x; pp[6].y = hi.y; pp[6].z = hi.z; pp[7].x = hi.x; pp[7].y = hi.y; pp[7].z = low.z; for( y = 0; y < 8; y++ ) pp[y] = world2cam1( &LWcam, pp[y] ); // now lets get the 2d bound low.x = 999999; low.y = 999999; low.z = 999999; hi.x = -999999; hi.y = -999999; hi.z = -999999; for( y = 0; y < 8; y++ ) { if( pp[y].x < low.x ) low.x = pp[y].x; if( pp[y].y < low.y ) low.y = pp[y].y; if( pp[y].z < low.z ) low.z = pp[y].z; if( pp[y].x > hi.x ) hi.x = pp[y].x; if( pp[y].y > hi.y ) hi.y = pp[y].y; if( pp[y].z > hi.z ) hi.z = pp[y].z; } // now, we tag the rectangle .. //// tag_tile_rect((int) floor(low.x),(int)floor(low.y),(int)ceil(hi.x),(int)ceil(hi.y), Gslg,GhairID, GnodeID); tag_tile_rect( ( int ) floor( low.x ), ( int ) floor( low.y ), ( int ) floor( hi.x ), ( int ) floor( hi.y ), Gslg, GhairID, GnodeID, triangles,Gcurpass ); // printf ("rect %d %d %d = %f %f | %f %f\n",Gslg,GhairID,GnodeID,floor(low.x),floor(low.y),ceil(hi.x),ceil(hi.y)); // fflush(stdout); } } } for( xx = 0; xx < wf->totalverts; xx++ ) { // wf->v[xx].z*= -1.0f; SHAVEcoord_convertFROMSHAVE( &wf->v[xx] ); SHAVEcoord_convertFROMSHAVE( &wf->vn[xx] ); } return ( success ); } static void WFdraw_oneINST( int x, int slg, int cs ) { int hc2 = 0; WFTYPE wf; int progress = 0; int finish = 0; CURVEINFO cinfo; init_geomWF( &wf ); Gcurpass = cs; { MAYAmake_a_hair( cs, slg, x, 10, &wf, &cinfo ); //progress++; Gslg = slg; GhairID = x; //if (progress>100) //if (TILEMODE==0) //{ // progress=0; //#ifndef EXTERNAL_COLLISION //global_progress++; // finish=SHAVEprogress(global_progress,estimated_total); //#endif //} if( matrixhair.killme == 0 ) { int q; int colorlk = 0; // for (q=0;q 0 ) free_geomWF( &wf ); } static void WFdraw_lotsINST( int cs ) { int hc2 = 0; WFTYPE wf; int x; int slg; int progress = 0; int finish = 0; int tcnnt = 0; int lpp = 0; reset_faces( ); checkforzero( ); Gcurpass = cs; mkbounds( ); weight_polys( ); texture_bounds( ); init_geomWF( &wf ); for( slg = 0; slg < 5; slg++ ) if( total_slgfaces[slg] > 0 ) { tcnnt += LOCAL_CNT[slg]; } tcnnt /= 40; if( freeze.totalverts > 0 ) for( x = 0; x < 5; x++ ) if( total_slgfaces[x] > 0 ) hc2++; if( freeze.totalverts > 0 ) if( hc2 > 0 ) for( slg = 0; slg < 5; slg++ ) if( total_slgfaces[slg] > 0 ) for( x = 0; x < LOCAL_CNT[slg]; x++ ) if( finish != 1 ) { Gslg = slg; GhairID = x; Gcurpass = cs; WFdraw_oneINST( x, slg, cs ); //if (TILEMODE==0) } if( freeze.totalverts > 0 ) free_geomWF( &wf ); } static void saveallINST( CHNG filename[255] ) { int x, yyy; FILE *fp; int hc2 = 0; int slg; int ti = 0; // FILE *rfp; int tv = 0; int tvv = 0; int lasttvv = 0; //for (x=0;x0) hc2++; for( x = 0; x < 5; x++ ) if( total_slgfaces[x] > 0 ) hc2++; fp = MYfopen( filename, _T("w") ); //rfp=fopen("tex.obj","w"); reset_faces( ); mkbounds( ); texture_bounds( ); weight_polys( ); //for (x=0;x 0 ) for( slg = 0; slg < 5; slg++ ) if( LOCAL_PASSES[slg] > 0 ) if( LOCAL_CNT[slg] > 0 ) if( total_slgfaces[slg] > 0 ) for( x = 0; x < LOCAL_CNT[slg]; x++ ) { int xx, yy; make_inst( slg, x ); if( matrixhair.dreadcount == 0 ) { xforminst( 0 ); Irelight( ); // draw_inst(); for( xx = 0; xx < freeze.totalverts; xx++ ) { fprintf( fp, "v %f %f %f\n", freezetmp.v[xx].x, freezetmp.v[xx].y, -freezetmp.v[xx].z ); fprintf( fp, "#vc %f %f %f\n", freezetmp.Rrvcolor[xx], freezetmp.Rgvcolor[xx], freezetmp.Rbvcolor[xx] ); // fprintf(rfp,"v %f %f %f\n",freeze.v[xx].x,freeze.v[xx].y,freeze.v[xx].z); } fprintf( fp, "usemtl colorlock" ); for( xx = 0; xx < freeze.totalfaces; xx++ ) { fprintf( fp, "f" ); // fprintf(rfp,"f"); // for (yy=freeze.face_start[xx];yy= freeze.face_start[xx]; yy-- ) { int g; int mm; mm = 1; g = freeze.facelist[yy] + tv; fprintf( fp, " %d", g + 1 + ti * freeze.totalverts * mm ); // fprintf(rfp," %d",g+1+x*freeze.totalverts); } fprintf( fp, "\n" ); // fprintf(rfp,"\n"); } } // dreadcount==0 if( matrixhair.dreadcount > 0 ) for( yy = 0; yy < matrixhair.dreadcount; yy++ ) { xforminst( yy ); Irelight( ); for( xx = 0; xx < freeze.totalverts; xx++ ) { fprintf( fp, "v %f %f %f\n", freezetmp.v[xx].x, freezetmp.v[xx].y, -freezetmp.v[xx].z ); fprintf( fp, "#vc %f %f %f\n", freezetmp.Rrvcolor[xx], freezetmp.Rgvcolor[xx], freezetmp.Rbvcolor[xx] ); tvv++; } } if( matrixhair.dreadcount > 0 ) fprintf( fp, "usemtl colorlock" ); if( matrixhair.dreadcount > 0 ) for( yy = 0; yy < matrixhair.dreadcount; yy++ ) for( xx = 0; xx < freeze.totalfaces; xx++ ) { fprintf( fp, "f" ); for( yyy = freeze.face_end[xx] - 1; yyy >= freeze.face_start[xx]; yyy-- ) { int g; // int mm; g = freeze.facelist[yyy] + tv; fprintf( fp, " %d", g + 1 + lasttvv + yy * freeze.totalverts ); } fprintf( fp, "\n" ); } ti++; lasttvv = tvv; // tvv+=(matrixhair.dreadcount-1)*(freeze.totalverts-1); } // local cnt fprintf( fp, "usemtl default\n" ); // for (x=0;x=Dface_start[x];y--) // { // fprintf(fp," %d",Dfacelist[y]+1); // } // fprintf(fp,"\n"); // } fclose( fp ); // fclose(rfp); } static int find_connect( int ls ) { int match = -1; int x; for( x = 0; x < Dtotallines; x++ ) { if( !Dtag[Dline_start[x]] ) if( Dline_start[x] == ls ) match = x; } return ( match ); } static void alloc_extra( int nv, int nf ) { if (facelistSP) free( facelistSP ); facelistSP=NULL; if (face_startSP) free( face_startSP ); face_startSP=NULL; if (face_endSP) free( face_endSP ); face_endSP=NULL; totalfvertsSP = 0; totalfacesSP = 0; if( ( nf > 0 ) && ( nv > 0 ) ) { facelistSP = ( int * ) malloc( nv * 23 * sizeof( int ) ); face_startSP = ( int * ) malloc( nf * 23 * sizeof( int ) ); face_endSP = ( int * ) malloc( nf * 32 * sizeof( int ) ); if( face_endSP == NULL ) { Glow_mem = 1; free_extra( ); DRAW_STATUS( "*** ERROR *** Out of Memory" ); } totalfvertsSP = 0; totalfacesSP = 0; } } static void free_extra( void ) { if( facelistSP != NULL ) free( facelistSP ); facelistSP = NULL; if (face_startSP) free( face_startSP ); face_startSP=NULL; if (face_endSP) free( face_endSP ); face_endSP=NULL; totalfvertsSP = 0; totalfacesSP = 0; totalfvertsSP = 0; totalfacesSP = 0; } static void fish_chains( void ) { int x, y; } static void relight_geom( FREEZETYPE * geom ) { int x; VERT lg1; int ll = 0; VERT vvn; for( x = 0; x < geom->totalfaces; x++ ) { int y; for( y = geom->face_start[x]; y < geom->face_end[x]; y++ ) { { int g; g = geom->facelist[y]; // restore locked color geom->Rrvcolor[g] = geom->Rrvcolor[g]; geom->Rgvcolor[g] = geom->Rgvcolor[g]; geom->Rbvcolor[g] = geom->Rbvcolor[g]; } } } for( x = 0; x < geom->totalverts; x++ ) { geom->rvcolor[x] = 0; geom->gvcolor[x] = 0; geom->bvcolor[x] = 0; } for( ll = 0; ll < totallights; ll++ ) if( LWlight[ll].xres > 0 ) if( LWlight[ll].radiosity == 0 ) if( LWlight[ll].caustics == 0 ) { double tmpp[3], tmpd[3], tmpc[3]; for( x = 0; x < geom->totalverts; x++ ) { // shading float spec; VERT eye, H; float shd; // int jk; VERT lum, lum2; tmpp[0] = geom->v[x].x; tmpp[1] = geom->v[x].y; tmpp[2] = geom->v[x].z; tmpc[0] = LWlight[ll].color.x; tmpc[1] = LWlight[ll].color.y; tmpc[2] = LWlight[ll].color.z; // hack tmpd[0] = LWlight[ll].wpos.x - ( float ) tmpp[0]; tmpd[1] = LWlight[ll].wpos.y - ( float ) tmpp[1]; tmpd[2] = LWlight[ll].wpos.z - ( float ) tmpp[2]; // jk=Gsa->illuminate(LWlight[ll].id,tmpp,tmpd,tmpc); lg1.x = ( float ) tmpd[0]; lg1.y = ( float ) tmpd[1]; lg1.z = ( float ) tmpd[2]; lg1 = Vnorm( lg1 ); lum.x = tmpc[0]; lum.y = tmpc[1]; lum.z = tmpc[2]; lum.x = 1.0f; lum.y = 1.0f; lum.z = 1.0f; lum2.x = 0; lum2.y = 0; lum2.z = 0; { // int ii; //for (ii=0;ii<3;ii++) { // VERT tlm; //tlm=cast_shadows_lgt(geom->v[x],ll); //lum2.x+=tlm.x/3.0f; //lum2.y+=tlm.y/3.0f; //lum2.z+=tlm.z/3.0f; } } lum2.x = 1.0f; lum2.y = 1.0f; lum2.z = 1.0f; lum.x *= lum2.x; lum.y *= lum2.y; lum.z *= lum2.z; eye.x = LWcam.wpos.x - geom->v[x].x; eye.y = LWcam.wpos.y - geom->v[x].y; eye.z = LWcam.wpos.z - geom->v[x].z; vvn = geom->vn[x]; shd = -vvn.x * lg1.x + -vvn.y * lg1.y + -vvn.z * lg1.z; if( shd < 0 ) shd = 0; shd *= matrixhair.diffuse; shd += ( 1.0f - matrixhair.diffuse ); // shd*=(matrixhair.ambient); // shd+=(1.0f-matrixhair.ambient); H.x = ( eye.x + lg1.x ) / 2.0f; H.y = ( eye.y + lg1.y ) / 2.0f; H.z = ( eye.z + lg1.z ) / 2.0f; H = Vnorm( H ); spec = dot( vvn, H ); if( spec < 0 ) spec = -spec; if( matrixhair.kspec > 0.0 ) spec = pow( spec, 1.0 / ( 3.0 * ( .101 - matrixhair.kspec ) ) ); // if (spec>1.0) spec=1.0f; if( spec < 0.0 ) spec = 0.0f; spec *= matrixhair.spec; spec *= 255; if( shd < ( ambient[0] + ambient[1] + ambient[2] ) / 3.0 ) shd = ( ambient[0] + ambient[1] + ambient[2] ) / 3.0f; if( shd > 1 ) shd = 1; geom->rvcolor[x] += ( ( shd * ( float ) geom->Rrvcolor[x] ) + spec ) * lum.x; geom->gvcolor[x] += ( ( shd * ( float ) geom->Rgvcolor[x] ) + spec ) * lum.y; geom->bvcolor[x] += ( ( shd * ( float ) geom->Rbvcolor[x] ) + spec ) * lum.z; if( geom->rvcolor[x] > 255 ) geom->rvcolor[x] = 255; if( geom->gvcolor[x] > 255 ) geom->gvcolor[x] = 255; if( geom->bvcolor[x] > 255 ) geom->bvcolor[x] = 255; if( geom->rvcolor[x] < 0 ) geom->rvcolor[x] = 0; if( geom->gvcolor[x] < 0 ) geom->gvcolor[x] = 0; if( geom->bvcolor[x] < 0 ) geom->bvcolor[x] = 0; // geom->rvcolor[x]+=((shd*(float)geom->Rrvcolor[x])+spec)*(float)tmpc[0]; // geom->gvcolor[x]+=((shd*(float)geom->Rgvcolor[x])+spec)*(float)tmpc[1]; // geom->bvcolor[x]+=((shd*(float)geom->Rbvcolor[x])+spec)*(float)tmpc[2]; // geom->rvcolor[x]+=((ambient[0]*(float)geom->Rrvcolor[x])+spec); // geom->gvcolor[x]+=((ambient[1]*(float)geom->Rgvcolor[x])+spec); // geom->bvcolor[x]+=((ambient[2]*(float)geom->Rbvcolor[x])+spec); } } } void MAYAdo_external_forces( int ext ) // 1 or 0 { if( ext == 0 ) EXTERNAL_COLLISIONS = 0; if( ext != 0 ) EXTERNAL_COLLISIONS = 1; } void MAYAset_gravity_vector( VERT vec ) { Ggravity_vector = vec; } int MAYAinsert_uv_coords( WFTYPE * uvin ) { int ret = 0; if( totalfaces > 0 ) if( uvin->totalfaces == Dtotalfaces ) { if( Guv.totalverts > 0 ) free_geomWF( &Guv ); Guv.totalverts = uvin->totalverts; Guv.totalfaces = uvin->totalfaces; Guv.totalfverts = uvin->totalfverts; alloc_geomWF( &Guv ); memcpy( &Guv, uvin, sizeof( uvin ) ); ret = 1; } return ( ret ); } void SHAVEreplace_rest( SHAVENODE * sn ) { int x; SHAVEID =(unsigned long) sn->restMEM.ID; MAYAset_parms( &sn->shavep ); #ifdef diagnose_trouble fprintf(stdout,"ID = %d clumps = %d replace rest\n",SHAVEID,Gclumps);fflush(stdout); #endif Gbeen_scaled = 1; SHAVEflush_state( sn ); // MAYArefresh(NULL,&sn->restMEM,&sn->statMEM,&sn->shavep); for( x = 0; x < totalverts; x++ ) memcpy( &hair[x].resthv, &hair[x].hv, sizeof( VERT ) * 15 ); for( x = 0; x < total_splines; x++ ) memcpy( &Shair[x], &Sresthair[x], sizeof( BASEHAIR ) ); for( x = 0; x < Dtotalverts; x++ ) { Drv[x] = Dv[x]; } // for (x=0;xrestMEM ); free_MEMFILE( &sn->statMEM ); Gbeen_scaled = 1; reset_noisespace( ); global_lastID = -1; MAYAfetch_node( &sn->restMEM, &sn->statMEM, &sn->shavep ); } #include "voxels.c" #ifdef VOLUMETRICLW //#include "atmosphere.c" #include "atmosphere.c" #endif #include "TriPoints.c" void SHAVEinvert_matrix( Matrix in, Matrix out ) { inverse( in, out ); } static void setup_toolbars( void ) { } static int Gfirst_draw_gl = 1; void init_a_hair( BASEHAIR * base ) { int x; int y; VERT zero; zero.x = 0.0f; zero.y = 0.0f; zero.z = 0.0f; base->vid = ( int ) 0; // for basehairs only base->uu = 0.0f; base->vv = 0.0f; base->restlength = 0.0f; base->sparerestlength = 0.0f; base->hide = ( short ) 0; base->mtl = 0; base->norm = zero; // for( y = 0; y < 4; y++ ) // for( x = 0; x < 4; x++ ) // base->mat[x][y] = 0.0f; // for( y = 0; y < 4; y++ ) // for( x = 0; x < 4; x++ ) // base->imat[x][y] = 0.0f; base->stiffness = ( float ) 0; base->pid = 0; base->slgroup = ( short ) 0; base->killme = ( short ) 0; base->hairnumber = 0; base->splitgroup = 0; base->splitmerge = 0; base->dreadroot = 0.0f; base->dreadtip = 0.0f; base->dreadcount = 0.0f; base->diffuse = 0.0f; base->spec = 0.0f; base->kspec = 0.0f; base->ambient = 0.0f; base->clumpfreq = 0.0f; base->kink = 0.0f; base->kinkfreq = 0.0f; base->rootfrizz = 0.0f; base->tipfrizz = 0.0f; base->frizzfreqX = 0.0f; base->frizzfreqY = 0.0f; base->frizzfreqZ = 0.0f; base->kinkfreqX = 0.0f; base->kinkfreqY = 0.0f; base->kinkfreqZ = 0.0f; base->randscale = 0.0f; base->frizzanim = 0.0f; base->animspeed = 0.0f; base->animdir = zero; base->cutlength = 0.0f; // base->freechain = ( char )0; // base->next = 0; base->thickness = 0.0f; base->thicknesstip = 0.0f; base->kinkroot = 0.0f; base->varval = 0.0f; base->trim = 0.0f; base->flyaway=0.0f; base->mess=0.0f; for( x = 0; x < 60; x++ ) base->slider[x] = 0.0f; for( x = 0; x < 15; x++ ) { base->pfID[x] = -1; base->w[x] = 0.0f; base->hv[x] = zero; base->lasthv[x] = zero; base->resthv[x] = zero; base->sparehv[x] = zero; base->velocity[x] = zero; base->color[x] = zero; base->select[x] = 0.0f; } } static void WFxplantNOMAT( CHNG file[555] ) { BASEHAIR base; //,restbase,noisebase; int oldmap[555]; int matmap[555]; int oldtotalverts; BASEHAIR *oldhair; // BASEHAIR *oldresthair; int oldsplines = -1; int *oldface_start = NULL; int *oldface_end = NULL; int *oldfacelist = NULL; int oldtotalfaces; int oldtotalfverts; int old_cnt[6]; int old_passes[6]; int x, y; float BIG; int vid; int oldmtl = -1; int oldskull_sphere = -1; //printf ("doing xplant\n"); reset_noisespace( ); //replace_rest(); init_a_hair( &base ); for( x = 0; x < 555; x++ ) oldmap[x] = -1; for( x = 0; x < 555; x++ ) matmap[x] = -1; for( x = 0; x < 5; x++ ) old_cnt[x] = LOCAL_CNT[x]; for( x = 0; x < 5; x++ ) old_passes[x] = LOCAL_PASSES[x]; // dissable locking for( x = 0; x < totalverts; x++ ) { for( y = 0; y < 15; y++ ) { { hair[x].pfID[y] = -1; // resthair[x].pfID[y]= -1; } } } for( x = 0; x < total_splines; x++ ) for( y = 0; y < 15; y++ ) { { Shair[x].pfID[y] = -1; Sresthair[x].pfID[y] = -1; } } oldskull_sphere = skull_sphere; oldtotalverts = totalverts; oldtotalfverts = totalfverts; oldtotalfaces = totalfaces; oldsplines = splines; oldmtl = head; oldhair = ( BASEHAIR * ) malloc( totalverts * sizeof( BASEHAIR ) ); // oldresthair=(BASEHAIR *) malloc (totalverts*sizeof(BASEHAIR)); oldfacelist = ( int * ) malloc( totalfverts * sizeof( int ) ); oldface_start = ( int * ) malloc( totalfaces * sizeof( int ) ); oldface_end = ( int * ) malloc( totalfaces * sizeof( int ) ); for( x = 0; x < totalverts; x++ ) { int y; memcpy( &oldhair[x], &hair[x], sizeof( BASEHAIR ) ); // memcpy(&oldresthair[x],&resthair[x],sizeof(BASEHAIR)); } for( x = 0; x < totalfverts; x++ ) oldfacelist[x] = facelist[x]; for( x = 0; x < totalfaces; x++ ) oldface_start[x] = face_start[x]; for( x = 0; x < totalfaces; x++ ) oldface_end[x] = face_end[x]; oldtotalverts = totalverts; for( x = 0; x < 5; x++ ) old_cnt[x] = LOCAL_CNT[x]; // SHAVEclear_stack( ); getobj( file ); // get the new model //printf ("planted hair on new object\n"); if( COLLISION_METHOD == 1 ) if( DOCOLLIDE ) { Dmake_normals( ); Dcalc_plane_eq( ); // norm is a unit vector setup_poly_vox( ); resize_poly_vox = 0; } if( DOCOLLIDE ) if( COLLISION_METHOD == 0 ) find_skulls( ); DRAW_STATUS( "Xfering hair" ); // ok now the old is approximately lined up with the new vid = -1; for( x = 0; x < totalverts; x++ ) { float smallest = 999991; BIG = ( float ) 999999.0f; // find 3 closest verts // find closest for( y = 0; y < oldtotalverts; y++ ) { float d; int chk = 0; // if (hair[x].mtl==matmap[oldhair[y].mtl]) // its a match // actually we don't care if( oldskull_sphere == -1 ) chk = 1; if( chk == 0 ) if( oldhair[y].mtl != oldskull_sphere ) chk = 1; if( chk == 1 ) { { int chk = 0; if( skull_sphere == -1 ) chk = 1; if( hair[x].mtl != skull_sphere ) if( skull_sphere != -1 ) chk = 1; if( chk == 1 ) // if (hair[x].mtl!=splines) // if ((oldsplines<0)||((oldsplines>=0)&&(oldhair[y].mtl!=oldsplines))) if( oldmtl != -1 ) if( oldhair[y].mtl == oldmtl ) { VERT a, b; a = hair[x].hv[0]; b = oldhair[y].hv[0]; d = Distance( a, b ); if( d < BIG ) { BIG = d; vid = y; } } // match } } } // y { // char tmp[255]; // sprintf(tmp,"%d",vid); // DRAW_STATUS(tmp); } //hair[x]=oldhair[x]; //vid=x; { int chk = 0; if( skull_sphere == -1 ) chk = 1; if( skull_sphere != -1 ) if( hair[x].mtl != skull_sphere ) chk = 1; if( chk == 1 ) if( vid >= 0 ) { // if (0==1) /// testing!! if( splines < 0 ) { memcpy( &base, &hair[x], sizeof( BASEHAIR ) ); //memcpy (&restbase,&resthair[x],sizeof(BASEHAIR)); // !! memcpy(&hair[x],&oldhair[vid],sizeof(BASEHAIR)); // !! memcpy(&resthair[x],&oldresthair[vid],sizeof(BASEHAIR)); } if( splines < 0 ) // testing !! { for( y = 0; y < 15; y++ ) { hair[x].hv[y] = oldhair[vid].hv[y]; hair[x].resthv[y] = oldhair[vid].resthv[y]; hair[x].lasthv[y] = oldhair[vid].lasthv[y]; hair[x].noisev[y] = oldhair[vid].noisev[y]; // resthair[x].hv[y]=oldresthair[vid].hv[y]; // resthair[x].noisev[y]=oldresthair[vid].noisev[y]; } } if( splines < 0 ) if( ( vid >= 0 ) ) for( y = 0; y < 15; y++ ) { // hair[x].hv[y]=oldhair[vid].hv[y]; hair[x].hv[y].x -= oldhair[vid].hv[0].x; hair[x].hv[y].y -= oldhair[vid].hv[0].y; hair[x].hv[y].z -= oldhair[vid].hv[0].z; hair[x].hv[y].x += base.hv[0].x; hair[x].hv[y].y += base.hv[0].y; hair[x].hv[y].z += base.hv[0].z; // hair[x].noisev[y]=oldhair[vid].noisev[y]; hair[x].noisev[y].x -= oldhair[vid].noisev[0].x; hair[x].noisev[y].y -= oldhair[vid].noisev[0].y; hair[x].noisev[y].z -= oldhair[vid].noisev[0].z; hair[x].noisev[y].x += base.noisev[0].x; hair[x].noisev[y].y += base.noisev[0].y; hair[x].noisev[y].z += base.noisev[0].z; hair[x].resthv[y] = oldhair[vid].resthv[y]; hair[x].resthv[y].x -= oldhair[vid].resthv[0].x; hair[x].resthv[y].y -= oldhair[vid].resthv[0].y; hair[x].resthv[y].z -= oldhair[vid].resthv[0].z; hair[x].resthv[y].x += base.resthv[0].x; hair[x].resthv[y].y += base.resthv[0].y; hair[x].resthv[y].z += base.resthv[0].z; hair[x].noisev[y] = oldhair[vid].noisev[y]; hair[x].noisev[y].x -= oldhair[vid].noisev[0].x; hair[x].noisev[y].y -= oldhair[vid].noisev[0].y; hair[x].noisev[y].z -= oldhair[vid].noisev[0].z; hair[x].noisev[y].x += base.noisev[0].x; hair[x].noisev[y].y += base.noisev[0].y; hair[x].noisev[y].z += base.noisev[0].z; } if( splines < 0 ) if( ( vid >= 0 ) ) //&&(vid[1]>0)&&(vid[2]>0)) { hair[x].restlength = oldhair[vid].restlength; //*scalar.x+ memcpy( &hair[x].lasthv, &hair[x].hv, sizeof( VERT ) * 15 ); } } } /// if (hair[x].restlength>0) /// recalc_hair(x); } // x mkbounds( ); reset_faces( ); checkforzero( ); Nfree( oldhair ); //Nfree(oldresthair); Nfree( oldfacelist ); Nfree( oldface_start ); Nfree( oldface_end ); check_wmaps( ); // LOCAL_CNT[0]=6500; // LOCAL_CNT[1]=1500; // LOCAL_CNT[2]=500; // LOCAL_CNT[3]=100; // LOCAL_CNT[4]=1500; for( x = 0; x < 5; x++ ) LOCAL_CNT[x] = old_cnt[x]; for( x = 0; x < 5; x++ ) LOCAL_PASSES[x] = old_passes[x]; reset_faces( ); checkforzero( ); //reset_faces(); DRAW_STATUS( "Done with Xfer" ); //for (x=0;x<5;x++) if (LOCAL_CNT!=0) LOCAL_CNT[x]=old_cnt[x]; //printf ("done with xplant\n"); reset_noisespace( ); } typedef struct { VERT p; float b1, b2, b3; } BARYVERT; void SHAVEspline_recomb( SHAVENODE * sn, WFTYPE * wf ) { int clfID1 = -1, clfID2 = -1, clfID3 = -1; int clptID1 = -1, clptID2 = -1, clptID3 = -1; float clptd1, clptd2, clptd3; int x, y; float d = -1.0f, cld = -1.0f; int clid = -1; BARYVERT bv[910]; //MAYAflush_state(&sn->restMEM,&sn->statMEM); // load node into engine SHAVEreplace_rest( sn ); // put_geomWF( wf, "c:\\splines_before.obj" ); if( Guse_restlength == 0 ) re_param_splines( wf ); // reparameterise curves else for( x = 0; x < wf->totalverts; x++ ) { wf->v[x].z *= -1.0f; // should be flipped } //put_geomWF(wf,"c:\\splines_after.obj"); for( x = 0; x < wf->totalverts; x++ ) wf->velocity[x].x = 0; for( x = 0; x < wf->totalverts; x++ ) wf->velocity[x].y = 0; // tag the end verts for( x = 0; x < wf->totalfaces; x++ ) { wf->velocity[wf->face_start[x]].x = 1; wf->velocity[wf->face_start[x]].y = ( float ) x; } for( x = 0; x < totalverts; x++ ) // cycle through the guides // if( hair[x].restlength != 0 ) // ok, find the 3 closest splines { { clptID1 = -1; clptID2 = -1; clptID3 = -1; clptd1 = 1000000.0f; clptd2 = 1000000.0f; clptd3 = 1000000.0f; for( y = 0; y < wf->totalverts; y++ ) if( wf->velocity[y].x != 0 ) // it's an end point { float dx, dy, dz; dx = wf->v[y].x - hair[x].hv[0].x; dy = wf->v[y].y - hair[x].hv[0].y; dz = wf->v[y].z - hair[x].hv[0].z; d = sqrt( dx * dx + dy * dy + dz * dz ); if( d < clptd1 ) // push points { clptd3 = clptd2; clptd2 = clptd1; clfID3 = clfID2; clfID2 = clfID1; clptID3 = clptID2; clptID2 = clptID1; clptID1 = y; clptd1 = d; clfID1 = ( int ) wf->velocity[y].y; // we've stuffed the face ID in here } else if( d < clptd2 ) // push points { clptd3 = clptd2; clfID3 = clfID2; clptID3 = clptID2; clptID2 = y; clptd2 = d; clfID2 = ( int ) wf->velocity[y].y; // we've stuffed the face ID in here } else if( d < clptd3 ) // push points { clptID3 = y; clptd3 = d; clfID3 = ( int ) wf->velocity[y].y; // we've stuffed the face ID in here } } } if( clptID2 == -1 ) { clptID2 = clptID1; clptd2 = clptd1; clfID2 = clfID1; } if( clptID3 == -1 ) { clptID3 = clptID2; clptd3 = clptd2; clfID3 = clfID2; } // now, we want to scatter some points with barycentric weights for( y = 0; y < 896; y++ ) { float s, t; float a, b, c; s = ( float ) drand98( ); //MTmix100(gs); t = ( float ) drand98( ); if( s + t > 1 ) { s = 1 - s; t = 1 - t; } a = s; b = t; c = ( 1 - s - t ); bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; } { float a, b, c; a = 1.0f; b = 0.0f; c = 0.0f; y = 896; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; a = 0.0f; b = 1.0f; c = 0.0f; y = 897; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; a = 0.0f; b = 0.0f; c = 1.0f; y = 898; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; a = 0.0f; b = 0.0f; c = 1.0f; y = 899; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; } // now, let's pick the closest one to the guide root { VERT gr; gr = hair[x].hv[0]; cld = 10000000.0f; for( y = 0; y < 899; y++ ) { float dx, dy, dz; dx = gr.x - bv[y].p.x; dy = gr.y - bv[y].p.y; dz = gr.z - bv[y].p.z; d = ( float ) sqrt( dx * dx + dy * dy + dz * dz ); if( d < cld ) { cld = d; clid = y; } } } //ok so, at this point we have a bary point, we can //printf ("clid = %d cld=%f\n",clid,cld); // stuff the spline's values into the guide for( y = 1; y < 15; y++ ) // we're assuming 15 verts { VERT vva, vvb, vvc; vva = wf->v[clptID1 + y]; vvb = wf->v[clptID2 + y]; vvc = wf->v[clptID3 + y]; //if (cld!=0) { hair[x].hv[y].x = vva.x * bv[clid].b1 + vvb.x * bv[clid].b2 + vvc.x * bv[clid].b3; hair[x].hv[y].y = vva.y * bv[clid].b1 + vvb.y * bv[clid].b2 + vvc.y * bv[clid].b3; hair[x].hv[y].z = vva.z * bv[clid].b1 + vvb.z * bv[clid].b2 + vvc.z * bv[clid].b3; } hair[x].hv[y].x -= bv[clid].p.x - hair[x].hv[0].x; hair[x].hv[y].y -= bv[clid].p.y - hair[x].hv[0].y; hair[x].hv[y].z -= bv[clid].p.z - hair[x].hv[0].z; hair[x].resthv[y] = hair[x].hv[y]; hair[x].noisev[y] = hair[x].hv[y]; } //re_param_base(&hair[x]); // if (Guse_restlength!=1) if( 0 == 1 ) { hair[x].restlength = Distance( hair[x].hv[2], hair[x].hv[3] ); hair[x].restlength += Distance( hair[x].hv[7], hair[x].hv[8] ); hair[x].restlength += Distance( hair[x].hv[12], hair[x].hv[13] ); hair[x].restlength /= 3.0f; } } Gbeen_scaled = 1; reset_rest( ); reset_noisespace( ); free_MEMFILE( &sn->restMEM ); free_MEMFILE( &sn->statMEM ); global_lastID = -1; MAYAfetch_node( &sn->restMEM, &sn->statMEM, &sn->shavep ); // replace the node // printf ("this is a 3.0 function - under construction..\n");fflush(stdout); SHAVEreplace_rest( sn ); reset_noisespace( ); for( x = 0; x < wf->totalverts; x++ ) { wf->v[x].z *= -1.0f; // should be flipped } } int XSI_GetRenderHairTriangle( int currsamp, int slg, int ind, int *out_prim, int *out_pva, int *out_pvb, int *out_pvc, float *out_pbarya, float *out_pbaryb ) { // Note: this code has to be kept in sync with draw_lotsWF() and // its sub-functions. Otherwise, the code that sub-divides // the hair to speed-up rendering won't work properly. int pd; int pid, i; int cloneON = ( sliders[25][slg].value > 0 ); int lp = LOCAL_PASSES[slg]; // Note: seems cc in the new 4.0.41 code no longer depends on // cloneON. // // Pierre Baillargeon, Innobec, 26 September 2006. // // int cc = (cloneON>0?1:( currsamp ) % lp); int cc = ( currsamp ) % lp; // This corresponds to the code paths tha tirgger killme? // Yep, it seems... // // Pierre Baillargeon. if( LOCAL_CNT[slg] == 0 || total_slgfaces[slg] == 0 ) return 0; if ( out_prim || out_pva || out_pvb || out_pvc ) { // Note: how the random-number generator is initialized depends on // the clone option. // // Pierre Baillargeon, Innobec, 26 September 2006. if ( cloneON == 0 ) Jsrand( ( unsigned long )( ind * 11 + cc * 6555 ) ); else Jsrand( ( unsigned long )( ind * 11 ) ); mixitup(); // Note: New randomizer code. No idea why Joe added this. // // Pierre Baillargeon, Innobec, 26 September 2006. for( pd = 0; pd < ( int )( 37. * ( float )drand98( ) + 10. * cc * ( float )drand98( ) ); pd++ ) drand98( ); if( slg == 4 ) { pid = ( floor ) ( ( float )drand98( ) * ( ( double )total_slgfaces[slg] - 1 ) - .000001f ); if( pid > total_slgfaces[slg] - 1 ) pid = total_slgfaces[slg] - 1; // Note: seems this was put in comments in Joe's code in 4.0.41. // // Pierre Baillargeon, Innobec, 26 September 2006. // //pid = slgfaces[slg][pid]; } else { do { pid = ( int )( ( float )drand98( ) * ( ( double )total_slgfaces[slg] ) - .000001f ); if( pid > total_slgfaces[slg] - 1 ) pid = total_slgfaces[slg] - 1; pid = slgfaces[slg][pid]; } while ( checkface( pid ) == 0 ); // Note: seems zero-length is no longer a criteria in Joe's code... // // Pierre Baillargeon, Innobec, 26 September 2006. // // Check it isn't zero length //for( i = face_start[pid]; i < face_end[pid]; i++ ) //{ // if ( hair[facelist[i]].restlength ) break; //} //if( i == face_end[pid] ) // return 0; } *out_prim = face_link[pid]; // Note: with hair 4.0.41, there are two sets of global variables: // with with normal names, the other beginning with D and it // all depends on slg's value. // // Pierre Baillargeon, Innobec, September 2006. if ( out_pva ) *out_pva = ( slg != 4 ? vlink[ facelist[ face_start[pid]]] : vlink[Dfacelist[Dface_start[pid]]] ); if ( out_pvb ) *out_pvb = ( slg != 4 ? vlink[ facelist[ face_start[pid] + 1]] : vlink[Dfacelist[Dface_start[pid] + 1]] ); if ( out_pvc ) *out_pvc = ( slg != 4 ? vlink[ facelist[ face_start[pid] + 2]] : -1 ); } if ( out_pbarya || out_pbaryb ) { float s, t; Jsrand( ( unsigned long )( ind * 11 + cc * 6555 ) ); // MTmix100(gs); s = ( float )drand98( ); // MTmix100(gs); t = ( float )drand98( ); if( s + t > 1 ) { s = 1 - s; t = 1 - t; } if ( out_pbarya ) *out_pbarya = s; if ( out_pbaryb ) *out_pbaryb = t; } return 1; } void XSI_EstimateHairProbability( int slg, unsigned long in_ulFaceIndex, double *out_pdProbability ) { if ( in_ulFaceIndex >= total_slgfaces[slg] ) { *out_pdProbability = 0; } else { // This code represents what check_face will do. int tr = 0, x; // Note: I removed the same code that was removed in checkface using // the same preprocessing convention as Joe. ;-) // // Pierre Baillargeon, Innobec, 21 September 2006. { // Estimate the number of hairs using the weight, and the total number of faces. // This takes poly_weight into account (used by checkface), as well as the probability that // this face is chosen. *out_pdProbability = ( poly_weight[in_ulFaceIndex]/total_slgfaces[slg] ); if ( *out_pdProbability == 0 ) { // Beep-de-beep. He uses <= poly_weight in checkface, so technically there // is a chance of getting a hair on this polygon. *out_pdProbability = 1e-273; } } } } void SHAVEspline_recombXPLANT( SHAVENODE * sn, WFTYPE * wf ); static void NEWWFxplant( CHNG file[555] ) { BASEHAIR base; //,restbase,noisebase; int oldmap[555]; int matmap[555]; int oldtotalverts; BASEHAIR *oldhair; // BASEHAIR *oldresthair; int oldsplines = -1; int *oldface_start = NULL; int *oldface_end = NULL; int *oldfacelist = NULL; int oldtotalfaces; int oldtotalfverts; int old_cnt[6]; int old_shadcnt[6]; int old_passes[6]; int x, y; float BIG; int vid; SHAVEPARMS shavep; WFTYPE meshguides; int oldmtl = -1; int oldskull_sphere = -1; SHAVENODE tmpnode; SHAVEinit_node( &tmpnode, 0 ); //printf ("doing xplant\n");fflush(stdout); reset_noisespace( ); //replace_rest(); global_lastID = -1; clear_uvsets( ); Gtotal_splinelocks= 0; init_geomWF( &meshguides ); { int tv = 0; tv = totalverts; if( tv != 0 ) { meshguides.totalverts = totalverts * 15; meshguides.totalfaces = totalverts; meshguides.totalfverts = totalverts * 15; alloc_geomWF( &meshguides ); for( x = 0; x < totalverts; x++ ) { meshguides.face_start[x] = x * 15; meshguides.face_end[x] = x * 15 + 15; // if (hair[x].restlength>0) for( y = 0; y < 15; y++ ) { int add = 0; add = x * 15 + y; meshguides.v[add] = hair[x].hv[y]; meshguides.v[add].z = hair[x].hv[y].z * -1.0f; // meshguides.color[add].x=hair[x].restlength; SHAVEcoord_convertFROMSHAVE( &meshguides.v[add] ); // meshguides.color[add] = hair[x].noisev[y]; meshguides.facelist[add] = add; // do we really want this? meshguides.velocity[add].x = 0; // if ( ((skull_sphere>=0)&&(hair[x].mtl!=skull_sphere))||(skull_sphere<0)) // meshguides.velocity[add].x=1; if( ( ( head >= 0 ) && ( hair[x].mtl == head ) ) ) meshguides.velocity[add].x = 1; } } } { int ok = 0; for( x = 0; x < meshguides.totalverts; x++ ) if( meshguides.velocity[x].x > 0 ) ok = 1; if( ok == 0 ) { printf( "none of the mesh guides were tagged with head materials\n" ); printf( "head material is set to = %d \n", head ); } } } SHAVEfetch_parms( &shavep ); SHAVEclear_stack( ); // getobj(file); // get the new model SHAVEcreate_node( file, &tmpnode ); //printf ("planted hair on new object\n"); if( COLLISION_METHOD == 1 ) if( DOCOLLIDE ) { Dmake_normals( ); Dcalc_plane_eq( ); // norm is a unit vector setup_poly_vox( ); resize_poly_vox = 0; } if( DOCOLLIDE ) if( COLLISION_METHOD == 0 ) find_skulls( ); Gbeen_scaled = 1; // SHAVEspline_recombXPLANT( &tmpnode, &meshguides ); Guse_restlength = 1; SHAVEspline_recomb( &tmpnode, &meshguides ); Guse_restlength = 0; Gbeen_scaled = 1; SHAVEset_parms( &shavep ); reset_noisespace( ); SHAVEfree_node( &tmpnode ); free_geomWF( &meshguides ); // printf("xplant !!\n");fflush(stdout); } void SHAVEspline_recombXPLANT( SHAVENODE * sn, WFTYPE * wf ) { int clfID1 = -1, clfID2 = -1, clfID3 = -1; int clptID1 = -1, clptID2 = -1, clptID3 = -1; float clptd1, clptd2, clptd3; int x, y; float d = -1.0f, cld = -1.0f; int clid = -1; BARYVERT bv[900]; int *xptag; //if (wf->totalverts==0) printf ("XPLANT: error - no guides to xplant!!\n"); //if (totalverts==0) printf ("XPLANT: error - no target geom!!\n"); if( totalverts > 0 ) if( wf->totalverts > 0 ) { //printf ("doing an xplant\n");fflush(stdout); //MAYAflush_state(&sn->restMEM,&sn->statMEM); // load node into engine SHAVEreplace_rest( sn ); xptag = ( int * ) malloc( ( totalverts + 10 ) * sizeof( int ) ); for( x = 0; x < totalverts; x++ ) xptag[x] = -1; // put_geomWF( wf, "c:\\splines_before.obj" ); //re_param_splines(wf); // reparameterise curves //put_geomWF(wf,"c:\\splines_after.obj"); // for( x = 0; x < wf->totalverts; x++ ) // wf->velocity[x].x = 0; // for( x = 0; x < wf->totalverts; x++ ) // wf->velocity[x].y = 0; // for( x = 0; x < wf->totalverts; x++ ) // wf->velocity[x].z = 0; // tag the end verts // for( x = 0; x < wf->totalfaces; x++ ) // { // wf->velocity[wf->face_start[x]].x = 1; // wf->velocity[wf->face_start[x]].y = ( float )x; // wf->velocity[wf->face_start[x]].z=Distance(wf->v[wf->face_start[x]],wf->v[wf->face_start[x]+1]); // } if( totalverts > 0 ) for( x = 0; x < totalverts; x++ ) // cycle through the guides // if( hair[x].restlength != 0 ) // ok, find the 3 closest splines { { clptID1 = -1; clptID2 = -1; clptID3 = -1; clptd1 = 999999999.0f; clptd2 = 999999999.0f; clptd3 = 999999999.0f; for( y = 0; y < wf->totalfaces; y++ ) if( wf->velocity[wf->face_start[y]].x > 0.0f ) { float dx, dy, dz; int q; q = wf->face_start[y]; dx = wf->v[q].x - hair[x].hv[0].x; dy = wf->v[q].y - hair[x].hv[0].y; dz = wf->v[q].z - hair[x].hv[0].z; d = sqrt( dx * dx + dy * dy + dz * dz ); if( d < .0001f ) { xptag[x] = q; // this face is equal !! } if( ( xptag[x] == 0 ) || ( d < clptd1 ) ) // push points { clptd3 = clptd2; clptd2 = clptd1; clfID3 = clfID2; clfID2 = clfID1; clptID3 = clptID2; clptID2 = clptID1; clptID1 = q; clptd1 = d; clfID1 = ( int ) y; // we've stuffed the face ID in here } else if( d < clptd2 ) // push points { if( xptag[x] == 0 ) { clptd3 = clptd2; clfID3 = clfID2; clptID3 = clptID2; clptID2 = q; clptd2 = d; clfID2 = ( int ) y; // we've stuffed the face ID in here } } else if( d < clptd3 ) // push points { if( xptag == 0 ) { clptID3 = q; clptd3 = d; clfID3 = ( int ) y; // we've stuffed the face ID in here } } } } if( clptID2 == -1 ) { clptID2 = clptID1; clptd2 = clptd1; clfID2 = clfID1; } if( clptID3 == -1 ) { clptID3 = clptID2; clptd3 = clptd2; clfID3 = clfID2; } if( x < 10 ) if( ( clptID1 < 0 ) && ( clptID2 < 0 ) && ( clptID3 < 0 ) ) printf( "an error has occured, there is no closest ref point for spline #%d\n", x ); // now, we want to scatter some points with barycentric weights if( xptag[x] == -1 ) { for( y = 0; y < 899; y++ ) { float s, t; float a, b, c; s = ( float ) drand98( ); //MTmix100(gs); t = ( float ) drand98( ); if( s + t > 1 ) { s = 1 - s; t = 1 - t; } a = s; b = t; c = ( 1 - s - t ); bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; } // now, let's pick the closest one to the guide root { VERT gr; gr = hair[x].hv[0]; cld = 999999999.0f; for( y = 0; y < 899; y++ ) { float dx, dy, dz; dx = gr.x - bv[y].p.x; dy = gr.y - bv[y].p.y; dz = gr.z - bv[y].p.z; d = ( float ) sqrt( dx * dx + dy * dy + dz * dz ); if( d < cld ) { cld = d; clid = y; } } } //ok so, at this point we have a bary point, we can // stuff the spline's values into the guide for( y = 1; y < 15; y++ ) // we're assuming 15 verts { VERT vva, vvb, vvc; vva = wf->v[clptID1 + y]; vvb = wf->v[clptID2 + y]; vvc = wf->v[clptID3 + y]; hair[x].hv[y].x = vva.x * bv[clid].b1 + vvb.x * bv[clid].b2 + vvc.x * bv[clid].b3; hair[x].hv[y].y = vva.y * bv[clid].b1 + vvb.y * bv[clid].b2 + vvc.y * bv[clid].b3; hair[x].hv[y].z = vva.z * bv[clid].b1 + vvb.z * bv[clid].b2 + vvc.z * bv[clid].b3; hair[x].hv[y].x -= bv[clid].p.x - hair[x].hv[0].x; hair[x].hv[y].y -= bv[clid].p.y - hair[x].hv[0].y; hair[x].hv[y].z -= bv[clid].p.z - hair[x].hv[0].z; hair[x].resthv[y] = hair[x].hv[y]; } hair[x].restlength = Distance( hair[x].hv[2], hair[x].hv[3] ); //re_param_base(&hair[x]); } if( xptag[x] != -1 ) for( y = 0; y < 15; y++ ) // we're assuming 15 verts { VERT vva, vvb, vvc; vva = wf->v[wf->facelist[xptag[x] + y]]; // vvb = wf->v[clptID2 + y]; // vvc = wf->v[clptID3 + y]; hair[x].hv[y] = vva; hair[x].resthv[y] = hair[x].hv[y]; hair[x].noisev[y] = hair[x].hv[y]; } } reset_rest( ); reset_noisespace( ); free_MEMFILE( &sn->restMEM ); free_MEMFILE( &sn->statMEM ); global_lastID = -1; MAYAfetch_node( &sn->restMEM, &sn->statMEM, &sn->shavep ); // replace the node //+ printf ("this is a 3.0 function - under construction..\n");fflush(stdout); SHAVEreplace_rest( sn ); reset_noisespace( ); free( xptag ); } } //static BASEHAIR draw_lotsWF2( int slg, int ind, VERT offs ); void mkHandles( void ) { int y; VERT vv; int x; // make_normals(); if( totalverts > 0 ) { for( x = 0; x < totalverts; x++ ) vnrest[x] = vn[x]; for( x = 0; x < totalverts; x++ ) { vv.x = hair[x].noisev[14].x - hair[x].noisev[0].x; vv.y = hair[x].noisev[14].y - hair[x].noisev[0].y; vv.z = hair[x].noisev[14].z - hair[x].noisev[0].z; vv = Vnorm( vv ); // if( ( vv.x < 0.00001f ) && ( vv.y < 0.00001f ) && ( vv.z < 0.00001f ) ) // { // vv.z = .1f; // vv.x += .0001f; // vv = Vnorm( vv ); // } // if( VDot( vv, vnrest[x] ) > .999 ) // { // vv.z = .1f; // vv.x += .0001f; // vv = Vnorm( vv ); // } vv = Vcross( vv, vnrest[x] ); vv = Vnorm( vv ); hair[x].resthandle = vv; hair[x].handle = vv; } for( y = 0; y < totalfaces; y++ ) for( x = face_start[y]; x < face_end[y]; x++ ) hair[facelist[x]].pid = y; } if( total_splines > 0 ) { for( x = 0; x < total_splines; x++ ) { VERT vvn; vv.x = Shair[x].noisev[14].x - Shair[x].noisev[0].x; vv.y = Shair[x].noisev[14].y - Shair[x].noisev[0].y; vv.z = Shair[x].noisev[14].z - Shair[x].noisev[0].z; vv = Vnorm( vv ); //vvn.x=Shair[x].noisev[1].x-Shair[x].noisev[0].x; //vvn.y=Shair[x].noisev[1].y-Shair[x].noisev[0].y; //vvn.z=Shair[x].noisev[1].z-Shair[x].noisev[0].z; //vvn=Vnorm(vvn); vvn = Shair[x].norm; if( VDot( vv, vvn ) > .999 ) { vv.z = .00001f; vv.x += .0001f; vv = Vnorm( vv ); } vv = Vcross( vv, vvn ); vv = Vnorm( vv ); Shair[x].resthandle = vv; Shair[x].handle = vv; } } } void xformHandles( void ) { VERT xxx, yyy, zzz; // int pid; VERT a, b; int y; Matrix m, im; int x; VERT zero; zero.x = 0; zero.y = 0; zero.z = 0; //if (totalverts>0) if( total_splines == 0 ) { for( y = 0; y < totalfaces; y++ ) for( x = face_start[y]; x < face_end[y]; x++ ) hair[facelist[x]].pid = y; //zero.x=1;zero.y=0;zero.z=0; //for (x=0;x=0)&&(hair[x].pid 0 ) { for( y = 0; y < total_splines; y++ ) Shair[y].pid = splinelist[y]; //zero.x=1;zero.y=0;zero.z=0; //for (x=0;x0) if( total_splines == 0 ) { //// may need to set pids for( y = 0; y < totalfaces; y++ ) //// for( x = face_start[y]; x < face_end[y]; x++ ) /// hair[facelist[x]].pid = y; //zero.x=1;zero.y=0;zero.z=0; //for (x=0;x=0)&&(hair[x].pid 0 ) { // may need to do this elsewhere // for( y = 0; y < total_splines; y++ ) /// Shair[y].pid = splinelist[y]; //zero.x=1;zero.y=0;zero.z=0; //for (x=0;x 0 ) Srecalc_hair2( x ); if( 0 == 1 ) // dynamics??? if( qq > 0 ) { int xx, y; for( xx = 0; xx < 15; xx++ ) Shair[x].sparehv[xx] = Shair[x].hv[xx]; if( scale_stat ) Shair[x].restlength = Distance( Shair[x].hv[0], Shair[x].hv[1] ); } // if( !scale_stat ) if( qq > 0 ) if( Gcollision_hit == 1 ) { Srecalc_hair2( x ); { int xx, y; Gcollision_hit = 0; for( xx = 0; xx < 15; xx++ ) Shair[x].sparehv[xx] = Shair[x].hv[xx]; } } // if( !scale_stat ) if( qq > 0 ) if( Gcollision_hit == 1 ) { Srecalc_hair2( x ); { int xx, y; Gcollision_hit = 0; for( xx = 0; xx < 15; xx++ ) Shair[x].sparehv[xx] = Shair[x].hv[xx]; } } } static void Srecalc_hair2( int g ) { int x; float r1; float stiff3; r1 = Shair[g].restlength; if( head >= 0 ) if( Shair[g].mtl == head ) stiff3 = sliders[8][0].value; if( beard >= 0 ) if( Shair[g].mtl == beard ) stiff3 = sliders[8][1].value; if( eyebrow >= 0 ) if( Shair[g].mtl == eyelash ) stiff3 = sliders[8][2].value; if( eyelash >= 0 ) if( Shair[g].mtl == eyebrow ) stiff3 = sliders[8][3].value; if( splines >= 0 ) if( Shair[g].mtl == splines ) stiff3 = sliders[8][4].value; //for (it=0;it<5;it++) if( r1 > 0 ) { // if (stiff3<.97) //repulse_hair(g); Srestore_locked_hair( g ); if( DOCOLLIDE ) { if( selmode != VERTS ) for( x = ( 15 - 2 ); x > 0; x-- ) // recalc from end first if( Shair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = Shair[g].hv[x]; b = Shair[g].hv[x + 1]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; if( selmode != VERTS ) Shair[g].hv[x] = a; if( ( selmode == VERTS ) && ( Shair[g].select[x] == 0 ) ) { Shair[g].hv[x] = a; } } Srestore_locked_hair( g ); Srepulse_hair( g ); for( x = 0; x < ( 15 - 1 ); x++ ) // recalc from root now if( Shair[g].pfID[x + 1] == -1 ) { VERT vec; VERT a, b, c; a = Shair[g].hv[x]; b = Shair[g].hv[x + 1]; vec = find_vector( a, b ); c.x = Shair[g].hv[x].x + ( vec.x * r1 ); c.y = Shair[g].hv[x].y + ( vec.y * r1 ); c.z = Shair[g].hv[x].z + ( vec.z * r1 ); if( selmode != VERTS ) Shair[g].hv[x + 1] = c; if( ( selmode == VERTS ) && ( Shair[g].select[x + 1] == 0 ) ) { Shair[g].hv[x + 1] = c; } } } Srestore_locked_hair( g ); // repulse_hair(g); // if it's VERTS do it again //if (selmode!=VERTS) for( x = ( 15 - 2 ); x > 0; x-- ) // recalc from end first if( Shair[g].pfID[x] == -1 ) { VERT vec; VERT a, b; a = Shair[g].hv[x]; b = Shair[g].hv[x + 1]; vec = find_vector( a, b ); a.x = b.x - vec.x * r1; a.y = b.y - vec.y * r1; a.z = b.z - vec.z * r1; Shair[g].hv[x] = a; } // if (stiff3<.97) // repulse_hair(g); // if (selmode==VERTS) for( x = 0; x < ( 15 - 1 ); x++ ) // recalc from root now if( Shair[g].pfID[x + 1] == -1 ) { VERT vec; VERT a, b, c; a = Shair[g].hv[x]; b = Shair[g].hv[x + 1]; vec = find_vector( a, b ); c.x = Shair[g].hv[x].x + ( vec.x * r1 ); c.y = Shair[g].hv[x].y + ( vec.y * r1 ); c.z = Shair[g].hv[x].z + ( vec.z * r1 ); Shair[g].hv[x + 1] = c; } Srestore_locked_hair( g ); Srepulse_hair( g ); } } static void Dweight_polys( void ) { int x; int y; // float *tmpwgt; // int *tmpcnt; double big = 0; double sz[3]; double area; // tmpwgt=(float *) malloc (totalverts*sizeof(float)); // tmpcnt=(int *) malloc (totalverts*sizeof(int)); // for (x=0;x 2 ) { int q = 0; int qq = 0, qq1, qq2; qq = Dfacelist[Dface_start[x]]; qq1 = Dfacelist[Dface_start[x] + 1]; qq2 = Dfacelist[Dface_start[x] + 2]; sz[0] = 0; sz[1] = 0; sz[2] = 0; if( distance( Dv[qq], Dv[qq1] ) + distance( Dv[qq1], Dv[qq2] ) + distance( Dv[qq2], Dv[qq] ) ) { for( y = Dface_start[x]; y <= Dface_start[x] + 2; y++ ) { int g, g1; g = Dfacelist[y]; if( y + 1 < Dface_end[x] ) { g1 = Dfacelist[y + 1]; } else g1 = Dfacelist[Dface_start[x]]; sz[q] = distance( Dv[g], Dv[g1] ); q++; } { float halfPerim; float a, b, c, tmp1, tmp2, tmp3, tmp4; a = sz[0]; b = sz[1]; c = sz[2]; // Calculate the area. //halfPerim = 0.5 * ( a + b + c ); //area = sqrt( halfPerim * (halfPerim-a) * (halfPerim-b) * (halfPerim-c) ); //Is that what's giving you the error? I know it can get numerically flaky when the triangle is needle-like...but if you're using double-precision it shouldn't really be a factor. If that *is* what you're doing, maybe you want to try this more stable version: // Sort the lengths biggest-smallest. //#ifdef crap if( b > a ) swap( b, a ); if( c > a ) swap( c, a ); if( c > b ) swap( c, b ); if( c < ( a - b ) ) c = ( a - b ); // Calculate the area. tmp1 = a + b + c; tmp2 = b - a + c; tmp3 = a - b + c; tmp4 = b - c + a; area = 0.25 * sqrt( tmp1 * tmp2 * tmp3 * tmp4 ); //#endif } if( big < area ) big = area; // big+=sz; } } // big*=big; for( x = 0; x < Dtotalfaces; x++ ) if( ( Dface_end[x] - Dface_start[x] ) > 2 ) { int q = 0; int qq = 0, qq1, qq2; qq = Dfacelist[Dface_start[x]]; qq1 = Dfacelist[Dface_start[x] + 1]; qq2 = Dfacelist[Dface_start[x] + 2]; sz[0] = 0; sz[1] = 0; sz[2] = 0; if( distance( Dv[qq], Dv[qq1] ) + distance( Dv[qq1], Dv[qq2] ) + distance( Dv[qq2], Dv[qq] ) ) { for( y = face_start[x]; y <= face_start[x] + 2; y++ ) { int g, g1; g = Dfacelist[y]; if( y + 1 < Dface_end[x] ) { g1 = Dfacelist[y + 1]; } else g1 = Dfacelist[Dface_start[x]]; sz[q] = distance( Dv[g], Dv[g1] ); q++; } { float halfPerim; float a, b, c, tmp1, tmp2, tmp3, tmp4; a = sz[0]; b = sz[1]; c = sz[2]; // Calculate the area. ///halfPerim = 0.5 * ( a + b + c ); ///area = sqrt( halfPerim * (halfPerim-a) * (halfPerim-b) * (halfPerim-c) ); //Is that what's giving you the error? I know it can get numerically flaky when the triangle is needle-like...but if you're using double-precision it shouldn't really be a factor. If that *is* what you're doing, maybe you want to try this more stable version: // Sort the lengths biggest-smallest. //#ifdef crap if( b > a ) swap( b, a ); if( c > a ) swap( c, a ); if( c > b ) swap( c, b ); //assert( c >= ( a - b ) ); if( c < ( a - b ) ) c = ( a - b ); // Calculate the area. tmp1 = a + b + c; tmp2 = b - a + c; tmp3 = a - b + c; tmp4 = b - c + a; area = 0.25 * sqrt( tmp1 * tmp2 * tmp3 * tmp4 ); //#endif //area *=area; if( big > 0.0 ) Dpoly_weight[x] = ( area ) / big; // if (x<1000) printf ("%f %f %f poly_weight[%d]=%f\n",a,b,c,x,poly_weight[x]);fflush(stdout); } // if (poly_weight[x]>1.0) // poly_weight[x]=1.0f; // poly_weight[x]=1.0f; } else Dpoly_weight[x] = 0.0f; } //Nfree(tmpwgt); //Nfree(tmpcnt); //printf ("big = %f\n",big); if( totalverts > 0 ) if( big < 0.00000001f ) DEGENERATE_OBJECT = 1; for( x = 0; x < total_splines; x++ ) { // if (Shair[x].restlength==0.0f) DEGENERATE_OBJECT=1; // if (Sresthair[x].restlength==0.0f) DEGENERATE_OBJECT=1; } } static void init_hairOLD( void ) { int x; if( Dtotalverts > 0 ) { DRAW_STATUS( "running auto-groom" ); // make_normals(); initbounds( ); //reset_faces(); //checkforzero(); regroup( ); skull_sphere = -1; for( x = 0; x < totalverts; x++ ) { int y; hair[x].vid = x; hair[x].restlength = 0.0f; for( y = 0; y < 15; y++ ) hair[x].hv[y] = v[x]; hair[x].mtl = vertgroup[x]; hair[x].slgroup = vertgroup[x]; } // grow hairs { int q; for( q = 0; q < totalgroups; q++ ) group_enable[q] = 0; for( q = 0; q < totalgroups; q++ ) { if( ( group_names[q][0] == 'b' ) && ( group_names[q][1] == 'e' ) && ( group_names[q][2] == 'a' ) && ( group_names[q][3] == 'r' ) && ( group_names[q][4] == 'd' ) ) { beard = q; group_enable[q] = 1; } if( ( group_names[q][0] == 's' ) && ( group_names[q][1] == 'k' ) && ( group_names[q][2] == 'u' ) && ( group_names[q][3] == 'l' ) ) { skull_sphere = q; group_enable[q] = 2; } if( ( group_names[q][0] == 's' ) && ( group_names[q][1] == 'p' ) && ( group_names[q][2] == 'l' ) && ( group_names[q][3] == 'i' ) && ( group_names[q][4] == 'n' ) ) { splines = q; group_enable[q] = 1; } if( ( group_names[q][0] == 'h' ) && ( group_names[q][1] == 'a' ) && ( group_names[q][2] == 'i' ) && ( group_names[q][3] == 'r' ) ) { head = q; group_enable[q] = 1; } if( ( group_names[q][0] == 'e' ) && ( group_names[q][1] == 'y' ) && ( group_names[q][2] == 'e' ) && ( group_names[q][3] == 'b' ) && ( group_names[q][4] == 'r' ) ) { eyebrow = q; group_enable[q] = 1; } if( ( group_names[q][0] == 'e' ) && ( group_names[q][1] == 'y' ) && ( group_names[q][2] == 'e' ) && ( group_names[q][3] == 'l' ) && ( group_names[q][4] == 'a' ) ) { eyelash = q; group_enable[q] = 1; } } make_normals( ); for( q = 0; q < totalverts; q++ ) hair[q].resthv[0] = v[q]; { /// int fv,lst,tv; for( q = 0; q < totalverts; q++ ) { int en; en = 0; if( skull_sphere == hair[q].mtl ) // for (fv=face_start[q];fv 0 ) { int q; DRAW_STATUS( "running auto-groom" ); // make_normals(); initbounds( ); //reset_faces(); //checkforzero(); // regroup( ); // skull_sphere = -1; for( x = 0; x < totalverts; x++ ) { int y; hair[x].vid = x; hair[x].restlength = 0.0f; for( y = 0; y < 15; y++ ) hair[x].hv[y] = v[x]; hair[x].mtl = vertgroup[x]; hair[x].slgroup = vertgroup[x]; } // grow hairs make_normals( ); for( q = 0; q < totalverts; q++ ) hair[q].resthv[0] = v[q]; { /// int fv,lst,tv; for( q = 0; q < totalverts; q++ ) { int en; en = 0; if( head != -1 ) if( head == hair[q].mtl ) // for (fv=face_start[q];fv 0 ) if( Dtag[x] ) { vn[Dlink[x]] = Dvn[x]; hair[Dlink[x]].norm = Dvn[x]; } } } static void DMakeFaceNormals( void ); static void Dmake_normals( void ) { int x, f, q; // SUBDmake_normals( ); // DMakeFaceNormals(); q = 0; for( x = 0; x < Dtotalverts; x++ ) { Dvn[x].x = 0.0f; Dvn[x].y = 0.0f; Dvn[x].z = 0.0f; } for( f = 0; f < Dtotalfaces; f++ ) if( ( Dface_end[f] - Dface_start[f] ) >= 3 ) { VERT v1, v2, v3; VERT uu, vv, cross; x = Dface_start[f]; v1 = Dv[Dfacelist[x + 2]]; v2 = Dv[Dfacelist[x + 1]]; v3 = Dv[Dfacelist[x + 0]]; 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 ); Dface_norm[f] = Vnorm( v1 ); // Dface_norm[f].x= -Dface_norm[f].x; // Dface_norm[f].y= -Dface_norm[f].y; // Dface_norm[f].z= -Dface_norm[f].z; for( x = Dface_start[f]; x < Dface_end[f]; x++ ) { // if ((!isnan_float(v1.x))&&(!isnan_float(v1.y))&&(!isnan_float(v1.z))) { Dvn[Dfacelist[x]].x += v1.x; Dvn[Dfacelist[x]].y += v1.y; Dvn[Dfacelist[x]].z += v1.z; } } } for( x = 0; x < Dtotalverts; x++ ) { float a, b, c, d; a = Dvn[x].x; b = Dvn[x].y; c = Dvn[x].z; d = sqrt( a * a + b * b + c * c ); if( d != 0.0f ) { a = a / d; b = b / d; c = c / d; } else { a += ( float ) 1.0f; } Dvn[x].x = a; Dvn[x].y = b; Dvn[x].z = c; //#ifdef wavefront // vn[x].x = -vn[x].x; // vn[x].y = -vn[x].y; // vn[x].z = -vn[x].z; //#endif } // relight(); //if (DOCOLLIDE) // Dcalc_plane_eq(); } static void make_hair_normals( void ) { int x, f, q; q = 0; for( x = 0; x < totalverts; x++ ) { hair[x].norm.x = 0.0f; hair[x].norm.y = 0.0f; hair[x].norm.z = 0.0f; // v[x]=hair[x].hv[0]; } for( f = 0; f < totalfaces; f++ ) if( ( face_end[f] - face_start[f] ) >= 3 ) { VERT v1, v2, v3; VERT uu, vv, cross; x = face_start[f]; v1 = hair[facelist[x + 2]].hv[0]; v2 = hair[facelist[x + 1]].hv[0]; v3 = hair[facelist[x + 0]].hv[0]; 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 ); // face_norm[f] = Vnorm( v1 ); // Dface_norm[f].x= -Dface_norm[f].x; // Dface_norm[f].y= -Dface_norm[f].y; // Dface_norm[f].z= -Dface_norm[f].z; for( x = face_start[f]; x < face_end[f]; x++ ) { // if ((!isnan_float(v1.x))&&(!isnan_float(v1.y))&&(!isnan_float(v1.z))) { hair[facelist[x]].norm.x += v1.x; hair[facelist[x]].norm.y += v1.y; hair[facelist[x]].norm.z += v1.z; } } } for( x = 0; x < totalverts; x++ ) { float a, b, c, d; a = hair[x].norm.x; b = hair[x].norm.y; c = hair[x].norm.z; d = sqrt( a * a + b * b + c * c ); if( d != 0.0f ) { a = a / d; b = b / d; c = c / d; } else { a += ( float ) 1.0f; } hair[x].norm.x = a; hair[x].norm.y = b; hair[x].norm.z = c; vn[x] = hair[x].norm; //#ifdef wavefront // vn[x].x = -vn[x].x; // vn[x].y = -vn[x].y; // vn[x].z = -vn[x].z; //#endif } // relight(); //if (DOCOLLIDE) // Dcalc_plane_eq(); } static void M_sproing( void ) { int x; testvar = 0; sproing2( ); for( x = 0; x < 5; x++ ) if( LOCAL_CNT[x] == 0 ) { LOCAL_PASSES[x] = 1; LOCAL_CNT[x] = 1500; LOCAL_SHADCNT[x] = 1500; } reset_faces( ); } static void M_sproing9( void ) { int x; testvar = 0; MS_sproing( 1.0f ); for( x = 0; x < 5; x++ ) if( LOCAL_CNT[x] == 0 ) { LOCAL_PASSES[x] = 1; LOCAL_CNT[x] = 1500; LOCAL_SHADCNT[x] = 1500; } checkforzero( ); } #ifdef EXTERNAL_COLLISION static void MSS_sproing( void ) { int x; testvar = 0; SOFTpop_select( 1.0f ); for( x = 0; x < 5; x++ ) if( LOCAL_CNT[x] == 0 ) { LOCAL_PASSES[x] = 1; LOCAL_CNT[x] = 1500; LOCAL_SHADCNT[x] = 1500; } checkforzero( ); } #endif void set_defaults( void ) { int x, y; // clear splits DOCOLLIDE = 0; /// Gbacklighting=1.0f; #ifdef EXTERNAL_COLLISION COLLISION_METHOD = 0; #endif // reset_noisespace(); totalsplits = 1; //Gclumps=0; for( x = 0; x < 60; x++ ) { Guv_link[x] = -1; } for( x = 0; x < 5; x++ ) { // Gsurface_collide[x] = 0; Ganim_dir[x].x = 0.0f; Ganim_dir[x].y = 1.0f; Ganim_dir[x].z = 0.0f; axis_tools[0][x].flags = 1; //28, 29, 44; // sprintf( axis_tools[0][x].lable, "Frizz Anim Dir" ); // sprintf( sliders[27][x].lable, "Splay (tip)" ); // sprintf( sliders[26][x].lable, "Splay (root)" ); // sprintf( sliders[25][x].lable, "Mult (strand cnt)" ); // sprintf( sliders[0][x].lable, "Frizz (root)" ); // sprintf( sliders[24][x].lable, "Frizz (tip)" ); // sprintf( sliders[1][x].lable, "Frizz freq X" ); // sprintf( sliders[30][x].lable, "Frizz freq Y" ); // sprintf( sliders[31][x].lable, "Frizz freq Z" ); // sprintf( sliders[32][x].lable, "Frizz anim" ); // sprintf( sliders[33][x].lable, "Anim speed" ); // sprintf( sliders[2][x].lable, "Kink (tip)" ); // sprintf( sliders[38][x].lable, "Kink (root)" ); // sprintf( sliders[3][x].lable, "Kink freq X" ); // sprintf( sliders[34][x].lable, "Kink freq Y" ); // sprintf( sliders[35][x].lable, "Kink freq Z" ); // sprintf( sliders[36][x].lable, "Rand scale" ); // sprintf( sliders[37][x].lable, "Thick (tip)" ); // sprintf( sliders[4][x].lable, "Specular" ); // sprintf( sliders[5][x].lable, "Gloss" ); // sprintf( sliders[6][x].lable, "Amb/Diff" ); // sprintf( sliders[7][x].lable, "Selfshadow" ); // sprintf( sliders[8][x].lable, "Stiffness" ); // sprintf( sliders[22][x].lable, "Wiggle Amp" ); // sprintf( sliders[23][x].lable, "Wiggle Spd" ); // sprintf( sliders[9][x].lable, "r" ); // sprintf( sliders[10][x].lable, "g" ); // sprintf( sliders[11][x].lable, "b" ); // sprintf( sliders[12][x].lable, "Var HUE +/-" ); // sprintf( sliders[39][x].lable, "Var VAL +/-" ); // sprintf( sliders[13][x].lable, "r" ); // sprintf( sliders[14][x].lable, "g" ); // sprintf( sliders[15][x].lable, "b" ); // sprintf( sliders[16][x].lable, "percent" ); // sprintf( sliders[17][x].lable, "r" ); // sprintf( sliders[18][x].lable, "g" ); // sprintf( sliders[19][x].lable, "b" ); // sprintf( sliders[20][x].lable, "Thick (root)" ); // sprintf( sliders[40][x].lable, "Dampening" ); // sprintf( sliders[21][x].lable, "Root Hold" ); // sprintf( sliders[41][x].lable, "Scale" ); // sprintf( sliders[42][x].lable, "Mult Randscale" ); // sprintf( sliders[43][x].lable, "Displace" ); // sprintf( sliders[44][x].lable, "twist" ); // sprintf( sliders[45][x].lable, "offset" ); // sprintf( sliders[46][x].lable, "aspect" ); // for( y = 0; y < 60; y++ ) // sliders[y][x].enable = 1; for( y = 0; y < 60; y++ ) Guv_link[y] = -1; // sliders[28][x].enable = 0; // sliders[29][x].enable = 0; //sliders[21][x].enable= 1; //sliders[40][x].enable= -1; } // if (total_slgfaces[0]>0) { LOCAL_SEGS[0] = 8; LOCAL_PASSES[0] = 1; LOCAL_CNT[0] = 4500; LOCAL_SHADCNT[0] = 4500; } // if (total_slgfaces[1]>0) { LOCAL_SEGS[1] = 10; LOCAL_PASSES[1] = 12; LOCAL_CNT[1] = 8500; } // if (total_slgfaces[2]>0) { LOCAL_SEGS[2] = 5; LOCAL_PASSES[2] = 8; LOCAL_CNT[2] = 200; } // if (total_slgfaces[3]>0) { LOCAL_SEGS[2] = 10; LOCAL_PASSES[3] = 3; LOCAL_CNT[3] = 100; } // if (total_slgfaces[4]>0) { LOCAL_SEGS[4] = 50; LOCAL_PASSES[4] = 4; LOCAL_CNT[4] = 250; LOCAL_SHADCNT[4] = 250; } for( x = 0; x < 5; x++ ) { #ifdef crap sprintf( sliders[0][x].lable, "Frizz (root)" ); sprintf( sliders[24][x].lable, "Frizz (tip)" ); sprintf( sliders[1][x].lable, "Frizz freq X" ); sprintf( sliders[30][x].lable, "Frizz freq Y" ); sprintf( sliders[31][x].lable, "Frizz freq Z" ); sprintf( sliders[2][x].lable, "Kink (root)" ); sprintf( sliders[3][x].lable, "Kink freq" ); sprintf( sliders[4][x].lable, "Specular" ); sprintf( sliders[5][x].lable, "Gloss" ); sprintf( sliders[6][x].lable, "Amb/Aiff" ); sprintf( sliders[7][x].lable, "Selfshadow" ); sprintf( sliders[8][x].lable, "Stiffness" ); sprintf( sliders[22][x].lable, "Wiggle Amp" ); sprintf( sliders[23][x].lable, "Wiggle Spd" ); sprintf( sliders[9][x].lable, "R" ); sprintf( sliders[10][x].lable, "G" ); sprintf( sliders[11][x].lable, "B" ); // sprintf(sliders[12][x].lable,"variation+/-"); sprintf( sliders[12][x].lable, "Var HUE +/-" ); sprintf( sliders[39][x].lable, "Var VAL +/-" ); sprintf( sliders[13][x].lable, "R" ); sprintf( sliders[14][x].lable, "G" ); sprintf( sliders[15][x].lable, "B" ); sprintf( sliders[16][x].lable, "percent" ); sprintf( sliders[17][x].lable, "R" ); sprintf( sliders[18][x].lable, "G" ); sprintf( sliders[19][x].lable, "B" ); sprintf( sliders[20][x].lable, "Thickness" ); sprintf( sliders[21][x].lable, "Root Stiffness" ); sprintf( sliders[41][x].lable, "Scale" ); sprintf( sliders[42][x].lable, "Mult Randscale" ); sprintf( sliders[43][x].lable, "Displacement" ); sprintf( sliders[44][x].lable, "Mult Aspect" ); lnmap[x].x = sliders[0][0].x; lnmap[x].y = sliders[21][x].y - 3; lnmap[x].paintbutton = 0; lnmap[x].sliderlink = 29; sprintf( lnmap[x].lable, "Cutmap" ); cmap[x].x = sliders[0][0].x; cmap[x].y = sliders[19][x].y - 18; cmap[x].paintbutton = -1; cmap[x].sliderlink = -1; sprintf( cmap[x].lable, "Colormap" ); dmap[x].x = sliders[0][0].x; dmap[x].y = sliders[21][x].y - 19; dmap[x].paintbutton = 0; dmap[x].sliderlink = 28; sprintf( dmap[x].lable, "Densmap" ); sprintf( sliders[28][x].lable, "Density" ); sprintf( sliders[29][x].lable, "Cutlength" ); axis_tools[0][x].x = sliders[33][0].x; axis_tools[0][x].y = sliders[33][x].y - 16; #endif } sliders[0][5].rangelow = -2.0f; sliders[0][5].rangehigh = 3.0f; sliders[0][5].value = 1.0f; collision_stat[0] = 1; collision_stat[1] = 0; collision_stat[2] = 0; collision_stat[3] = 0; // dreadlock // hair sliders[27][0].rangelow = 0; sliders[27][0].rangehigh = 1.5f; sliders[27][0].value = 0.0f; // beard sliders[27][1].rangelow = 0; sliders[27][1].rangehigh = 1.5f; sliders[27][1].value = 0.0f; // brow sliders[27][2].rangelow = 0; sliders[27][2].rangehigh = 1.5f; sliders[27][2].value = 0.0f; // lids sliders[27][3].rangelow = 0; sliders[27][3].rangehigh = 1.5f; sliders[27][3].value = 0.0f; // hair sliders[26][0].rangelow = 0; sliders[26][0].rangehigh = 1.5f; sliders[26][0].value = 0.0f; // beard sliders[26][1].rangelow = 0; sliders[26][1].rangehigh = 1.5f; sliders[26][1].value = 0.0f; // brow sliders[26][2].rangelow = 0; sliders[26][2].rangehigh = 1.5f; sliders[26][2].value = 0.0f; // lids sliders[26][3].rangelow = 0; sliders[26][3].rangehigh = 1.5f; sliders[26][3].value = 0.0f; // clump // hair sliders[0][0].rangelow = 0.0f; sliders[0][0].rangehigh = 180.0f; sliders[0][0].value = 15.5f; // beard sliders[0][1].rangelow = 0.0f; sliders[0][1].rangehigh = 180.0f; sliders[0][1].value = 13.5f; // brow sliders[0][2].rangelow = 0.0f; sliders[0][2].rangehigh = 180.0f; sliders[0][2].value = 3.5f; // lids sliders[0][3].rangelow = 0.0f; sliders[0][3].rangehigh = 180.0f; sliders[0][3].value = 3.5f; // clump freq // hair sliders[1][0].rangelow = .001f; sliders[1][0].rangehigh = 1500.0f; sliders[1][0].value = 214.4f; // beard sliders[1][1].rangelow = .005f; sliders[1][1].rangehigh = 1500.0f; sliders[1][1].value = 114.4f; // brow sliders[1][2].rangelow = .005f; sliders[1][2].rangehigh = 1500.0f; sliders[1][2].value = 114.4f; // lids sliders[1][3].rangelow = 0.005f; sliders[1][3].rangehigh = 1500.0f; sliders[1][3].value = 114.4f; // frizz freq y // hair sliders[30][0].rangelow = .001f; sliders[30][0].rangehigh = 1500.0f; sliders[30][0].value = 214.4f; // beard sliders[30][1].rangelow = 0.005f; sliders[30][1].rangehigh = 1500.0f; sliders[30][1].value = 114.4f; // brow sliders[30][2].rangelow = 0.005f; sliders[30][2].rangehigh = 1500.0f; sliders[30][2].value = 114.4f; // lids sliders[30][3].rangelow = 0.005f; sliders[30][3].rangehigh = 1500.0f; sliders[30][3].value = 114.4f; // frizz freq z // hair sliders[31][0].rangelow = 0.001f; sliders[31][0].rangehigh = 1500.0f; sliders[31][0].value = 214.4f; // beard sliders[31][1].rangelow = 0.005f; sliders[31][1].rangehigh = 1500.0f; sliders[31][1].value = 114.4f; // brow sliders[31][2].rangelow = 0.005f; sliders[31][2].rangehigh = 1500.0f; sliders[31][2].value = 114.4f; // lids sliders[31][3].rangelow = 0.005f; sliders[31][3].rangehigh = 1500.0f; sliders[31][3].value = 114.4f; // frizz anim // hair sliders[32][0].rangelow = 0.0f; sliders[32][0].rangehigh = 1.0f; sliders[32][0].value = 0.0f; sliders[32][1].rangelow = 0.0f; sliders[32][1].rangehigh = 1.0f; sliders[32][1].value = 0.0f; sliders[32][2].rangelow = 0.0f; sliders[32][2].rangehigh = 1.0f; sliders[32][2].value = 0.0f; sliders[32][3].rangelow = 0.0f; sliders[32][3].rangehigh = 1.0f; sliders[32][3].value = 0.0f; // frizz speed // hair sliders[33][0].rangelow = -1.0f; sliders[33][0].rangehigh = 1.0f; sliders[33][0].value = 0.0f; sliders[33][1].rangelow = -1.0f; sliders[33][1].rangehigh = 1.0f; sliders[33][1].value = 0.0f; sliders[33][2].rangelow = -1.0f; sliders[33][2].rangehigh = 1.0f; sliders[33][2].value = 0.0f; sliders[33][3].rangelow = -1.0f; sliders[33][3].rangehigh = 1.0f; sliders[33][3].value = 0.0f; // thick (tip) // hair sliders[37][0].rangelow = 0.0f; sliders[37][0].rangehigh = 2.0f; sliders[37][0].value = 0.0f; sliders[37][1].rangelow = 0.0f; sliders[37][1].rangehigh = 2.0f; sliders[37][1].value = 0.0f; sliders[37][2].rangelow = 0.0f; sliders[37][2].rangehigh = 2.0f; sliders[37][2].value = 0.0f; sliders[37][3].rangelow = 0.0f; sliders[37][3].rangehigh = 2.0f; sliders[37][3].value = 0.0f; // kink // hair sliders[2][0].rangelow = 0; sliders[2][0].rangehigh = 50.0f; sliders[2][0].value = 0.0f; // beard sliders[2][1].rangelow = 0; sliders[2][1].rangehigh = 25.0f; sliders[2][1].value = 0.0f; // brow sliders[2][2].rangelow = 0; sliders[2][2].rangehigh = 25.0f; sliders[2][2].value = 0.0f; // lids sliders[2][3].rangelow = 0; sliders[2][3].rangehigh = 25.0f; sliders[2][3].value = 0.0f; // kink tip // hair sliders[38][0].rangelow = 0; sliders[38][0].rangehigh = 30.0f; sliders[38][0].value = 0.0f; // beard sliders[38][1].rangelow = 0; sliders[38][1].rangehigh = 15.0f; sliders[38][1].value = 0.0f; // brow sliders[38][2].rangelow = 0; sliders[38][2].rangehigh = 15.0f; sliders[38][2].value = 0.0f; // lids sliders[38][3].rangelow = 0; sliders[38][3].rangehigh = 15.0f; sliders[38][3].value = 0.0f; // kink freq // hair sliders[3][0].rangelow = .01f; sliders[3][0].rangehigh = 40.0f; sliders[3][0].value = 23.0f; // beard sliders[3][1].rangelow = .01f; sliders[3][1].rangehigh = 80.0f; sliders[3][1].value = 23.0f; // brow sliders[3][2].rangelow = .01f; sliders[3][2].rangehigh = 80.0f; sliders[3][2].value = 23.0f; // lids sliders[3][3].rangelow = .01f; sliders[3][3].rangehigh = 80.0f; sliders[3][3].value = 23.0f; // kink freq Y // hair sliders[34][0].rangelow = .01f; sliders[34][0].rangehigh = 40.0f; sliders[34][0].value = 23.0f; // beard sliders[34][1].rangelow = .01f; sliders[34][1].rangehigh = 80.0f; sliders[34][1].value = 23.0f; // brow sliders[34][2].rangelow = .01f; sliders[34][2].rangehigh = 80.0f; sliders[34][2].value = 23.0f; // lids sliders[34][3].rangelow = .01f; sliders[34][3].rangehigh = 80.0f; sliders[34][3].value = 23.0f; // kink freq z // hair sliders[35][0].rangelow = .01f; sliders[35][0].rangehigh = 40.0f; sliders[35][0].value = 23.0f; // beard sliders[35][1].rangelow = .01f; sliders[35][1].rangehigh = 80.0f; sliders[35][1].value = 23.0f; // brow sliders[35][2].rangelow = .01f; sliders[35][2].rangehigh = 80.0f; sliders[35][2].value = 23.0f; // lids sliders[35][3].rangelow = .01f; sliders[35][3].rangehigh = 80.0f; sliders[35][3].value = 23.0f; // rand scale // hair sliders[36][0].rangelow = .00f; sliders[36][0].rangehigh = 1.0f; sliders[36][0].value = 0.4f; // beard sliders[36][1].rangelow = .0f; sliders[36][1].rangehigh = 1.0f; sliders[36][1].value = 0.0f; // brow sliders[36][2].rangelow = .0f; sliders[36][2].rangehigh = 1.0f; sliders[36][2].value = 0.0f; // lids sliders[36][3].rangelow = .0f; sliders[36][3].rangehigh = 1.0f; sliders[36][3].value = 0.0f; // spec // hair sliders[4][0].rangelow = 0.0f; sliders[4][0].rangehigh = 1.5f; sliders[4][0].value = .9f; // beard sliders[4][1].rangelow = 0.0f; sliders[4][1].rangehigh = 1.5f; sliders[4][1].value = .9f; // brow sliders[4][2].rangelow = 0.0f; sliders[4][2].rangehigh = 1.5f; sliders[4][2].value = .9f; // lids sliders[4][3].rangelow = 0.0f; sliders[4][3].rangehigh = 1.5f; sliders[4][3].value = .9f; // Kspec // hair sliders[5][0].rangelow = .0801f; sliders[5][0].rangehigh = .1f; sliders[5][0].value = .098f; // beard sliders[5][1].rangelow = .0801f; sliders[5][1].rangehigh = .1f; sliders[5][1].value = .098f; // brow sliders[5][2].rangelow = 0.0801f; sliders[5][2].rangehigh = .1f; sliders[5][2].value = .098f; // lids sliders[5][3].rangelow = 0.0801f; sliders[5][3].rangehigh = .1f; sliders[5][3].value = .098f; // diffuse // hair sliders[6][0].rangelow = 0.0f; sliders[6][0].rangehigh = 1.0f; sliders[6][0].value = .75f; // beard sliders[6][1].rangelow = 0.0f; sliders[6][1].rangehigh = 1.0f; sliders[6][1].value = .75f; // brow sliders[6][2].rangelow = 0.0f; sliders[6][2].rangehigh = 1.0f; sliders[6][2].value = .75f; // lids sliders[6][3].rangelow = 0.0f; sliders[6][3].rangehigh = 1.0f; sliders[6][3].value = .75f; // ambient - self shad // hair sliders[7][0].rangelow = 0.0f; sliders[7][0].rangehigh = 1.0f; sliders[7][0].value = 0.75f; // beard sliders[7][1].rangelow = 0.0f; sliders[7][1].rangehigh = 1.0f; sliders[7][1].value = 0.85f; // brow sliders[7][2].rangelow = 0.0f; sliders[7][2].rangehigh = 1.0f; sliders[7][2].value = 0.85f; // lids sliders[7][3].rangelow = 0.0f; sliders[7][3].rangehigh = 1.0f; sliders[7][3].value = 0.85f; // dynamics - stiffness // hair sliders[8][0].rangelow = .05f; sliders[8][0].rangehigh = 1.0f; sliders[8][0].value = 0.4f; // beard sliders[8][1].rangelow = .05f; sliders[8][1].rangehigh = 1.0f; sliders[8][1].value = 1.0f; // brow sliders[8][2].rangelow = .05f; sliders[8][2].rangehigh = 1.0f; sliders[8][2].value = 1.0f; // lids sliders[8][3].rangelow = .05f; sliders[8][3].rangehigh = 1.0f; sliders[8][3].value = 1.0f; sliders[8][4].rangelow = .05f; sliders[8][4].rangehigh = 1.0f; sliders[8][4].value = .7f; // main red // hair sliders[9][0].rangelow = 0.0f; sliders[9][0].rangehigh = 255.0f; sliders[9][0].value = 100.0f; // beard sliders[9][1].rangelow = 0.0f; sliders[9][1].rangehigh = 255.0f; sliders[9][1].value = 100.0f; // brow sliders[9][2].rangelow = 0.0f; sliders[9][2].rangehigh = 255.0f; sliders[9][2].value = 100.0f; // lids sliders[9][3].rangelow = 0.0f; sliders[9][3].rangehigh = 255.0f; sliders[9][3].value = 100.0f; // main green // hair sliders[10][0].rangelow = 0.0f; sliders[10][0].rangehigh = 255.0f; sliders[10][0].value = 100.0f; // beard sliders[10][1].rangelow = 0.0f; sliders[10][1].rangehigh = 255.0f; sliders[10][1].value = 80.0f; // brow sliders[10][2].rangelow = 0.0f; sliders[10][2].rangehigh = 255.0f; sliders[10][2].value = 80.0f; // lids sliders[10][3].rangelow = 0.0f; sliders[10][3].rangehigh = 255.0f; sliders[10][3].value = 80.0f; // main blue // hair sliders[11][0].rangelow = 0.0f; sliders[11][0].rangehigh = 255.0f; sliders[11][0].value = 100.0f; // beard sliders[11][1].rangelow = 0.0f; sliders[11][1].rangehigh = 255.0f; sliders[11][1].value = 55.0f; // brow sliders[11][2].rangelow = 0.0f; sliders[11][2].rangehigh = 255.0f; sliders[11][2].value = 55.0f; // lids sliders[11][3].rangelow = 0.0f; sliders[11][3].rangehigh = 255.0f; sliders[11][3].value = 55.0f; // main variation // hair sliders[12][0].rangelow = 0.0f; sliders[12][0].rangehigh = 50.0f; sliders[12][0].value = 30.0f; // beard sliders[12][1].rangelow = 0.0f; sliders[12][1].rangehigh = 50.0f; sliders[12][1].value = 10.0f; // brow sliders[12][2].rangelow = 0.0f; sliders[12][2].rangehigh = 50.0f; sliders[12][2].value = 10.0f; // lids sliders[12][3].rangelow = 0.0f; sliders[12][3].rangehigh = 50.0f; sliders[12][3].value = 10.0f; // main variation luminance // hair sliders[39][0].rangelow = 0.0f; sliders[39][0].rangehigh = 100.0f; sliders[39][0].value = 50.0f; // beard sliders[39][1].rangelow = 0.0f; sliders[39][1].rangehigh = 100.0f; sliders[39][1].value = 50.0f; // brow sliders[39][2].rangelow = 0.0f; sliders[39][2].rangehigh = 100.0f; sliders[39][2].value = 50.0f; // lids sliders[39][3].rangelow = 0.0f; sliders[39][3].rangehigh = 100.0f; sliders[39][3].value = 50.0f; // second red // hair sliders[13][0].rangelow = 00.0f; sliders[13][0].rangehigh = 255.0f; sliders[13][0].value = 120.0f; // beard sliders[13][1].rangelow = 0.0f; sliders[13][1].rangehigh = 255.0f; sliders[13][1].value = 120.0f; // brow sliders[13][2].rangelow = 0.0f; sliders[13][2].rangehigh = 255.0f; sliders[13][2].value = 120.0f; // lids sliders[13][3].rangelow = 0.0f; sliders[13][3].rangehigh = 255.0f; sliders[13][3].value = 120.0f; // second green // hair sliders[14][0].rangelow = 0.0f; sliders[14][0].rangehigh = 255.0f; sliders[14][0].value = 120.0f; // beard sliders[14][1].rangelow = 0.0f; sliders[14][1].rangehigh = 255.0f; sliders[14][1].value = 75.0f; // brow sliders[14][2].rangelow = 0.0f; sliders[14][2].rangehigh = 255.0f; sliders[14][2].value = 75.0f; // lids sliders[14][3].rangelow = 0.0f; sliders[14][3].rangehigh = 255.0f; sliders[14][3].value = 75.0f; // second blue // hair sliders[15][0].rangelow = 0.0f; sliders[15][0].rangehigh = 255.0f; sliders[15][0].value = 120.0f; // beard sliders[15][1].rangelow = 0.0f; sliders[15][1].rangehigh = 255.0f; sliders[15][1].value = 35.0f; // brow sliders[15][2].rangelow = 0.0f; sliders[15][2].rangehigh = 255.0f; sliders[15][2].value = 35.0f; // lids sliders[15][3].rangelow = 0.0f; sliders[15][3].rangehigh = 255.0f; sliders[15][3].value = 35.0f; // second percent // hair sliders[16][0].rangelow = 0.0f; sliders[16][0].rangehigh = 15.0f; sliders[16][0].value = 0.0f; // beard sliders[16][1].rangelow = 0.0f; sliders[16][1].rangehigh = 15.0f; sliders[16][1].value = 0.0f; // brow sliders[16][2].rangelow = 0.0f; sliders[16][2].rangehigh = 15.0f; sliders[16][2].value = 0.0f; // lids sliders[16][3].rangelow = 0.0f; sliders[16][3].rangehigh = 15.0f; sliders[16][3].value = 5.0f; // third red // hair sliders[17][0].rangelow = 0; sliders[17][0].rangehigh = 255.0f; sliders[17][0].value = 100.0f; // beard sliders[17][1].rangelow = 0; sliders[17][1].rangehigh = 255.0f; sliders[17][1].value = 100.0f; // brow sliders[17][2].rangelow = 0; sliders[17][2].rangehigh = 255.0f; sliders[17][2].value = 100.0f; // lids sliders[17][3].rangelow = 0; sliders[17][3].rangehigh = 255.0f; sliders[17][3].value = 100.0f; // third green // hair sliders[18][0].rangelow = 0; sliders[18][0].rangehigh = 255.0f; sliders[18][0].value = 100.0f; // beard sliders[18][1].rangelow = 0; sliders[18][1].rangehigh = 255.0f; sliders[18][1].value = 80.0f; // brow sliders[18][2].rangelow = 0; sliders[18][2].rangehigh = 255.0f; sliders[18][2].value = 80.0f; // lids sliders[18][3].rangelow = 0; sliders[18][3].rangehigh = 255.0f; sliders[18][3].value = 80.0f; // third blue // hair sliders[19][0].rangelow = 0; sliders[19][0].rangehigh = 255.0f; sliders[19][0].value = 100.0f; // beard sliders[19][1].rangelow = 0; sliders[19][1].rangehigh = 255.0f; sliders[19][1].value = 50.0f; // brow sliders[19][2].rangelow = 0; sliders[19][2].rangehigh = 255.0f; sliders[19][2].value = 50.0f; // lids sliders[19][3].rangelow = 0; sliders[19][3].rangehigh = 255.0f; sliders[19][3].value = 50.0f; // thickness // hair sliders[20][0].rangelow = 0.0f; sliders[20][0].rangehigh = 2.0f; sliders[20][0].value = .76f; // beard sliders[20][1].rangelow = 0.0f; sliders[20][1].rangehigh = 2.0f; sliders[20][1].value = .78f; // brow sliders[20][2].rangelow = 0.0f; sliders[20][2].rangehigh = 2.0f; sliders[20][2].value = .18f; // lids sliders[20][3].rangelow = 0.0f; sliders[20][3].rangehigh = 2.0f; sliders[20][3].value = .18f; // stiffness root // hair sliders[21][0].rangelow = 0.0f; sliders[21][0].rangehigh = 1.0f; sliders[21][0].value = 1.0f; // beard sliders[21][1].rangelow = 0.0f; sliders[21][1].rangehigh = 1.0f; sliders[21][1].value = 1.0f; // brow sliders[21][2].rangelow = 0.0f; sliders[21][2].rangehigh = 1.0f; sliders[21][2].value = 1.0f; // lids sliders[21][3].rangelow = 0.0f; sliders[21][3].rangehigh = 1.0f; sliders[21][3].value = 1.0f; // dampening force // hair sliders[40][0].rangelow = 0.0f; sliders[40][0].rangehigh = 1.0f; sliders[40][0].value = 0.0f; // beard sliders[40][1].rangelow = 0.0f; sliders[40][1].rangehigh = 1.0f; sliders[40][1].value = 0.0f; // brow sliders[40][2].rangelow = 0.0f; sliders[40][2].rangehigh = 1.0f; sliders[40][2].value = 0.0f; // lids sliders[40][3].rangelow = 0.0f; sliders[40][3].rangehigh = 1.0f; sliders[40][3].value = 0.0f; sliders[40][4].rangelow = 0.0f; sliders[40][4].rangehigh = 1.0f; sliders[40][4].value = 0.0f; // wiggle amp // hair sliders[22][0].rangelow = 0.0f; sliders[22][0].rangehigh = 1.0f; sliders[22][0].value = 0.0f; // beard sliders[22][1].rangelow = 0.0f; sliders[22][1].rangehigh = 1.0f; sliders[22][1].value = 0.0f; // brow sliders[22][2].rangelow = 0.0f; sliders[22][2].rangehigh = 1.0f; sliders[22][2].value = 0.0f; // lids sliders[22][3].rangelow = 0.0f; sliders[22][3].rangehigh = 1.0f; sliders[22][3].value = 0.0f; // wiggle speed // hair sliders[23][0].rangelow = 0.0f; sliders[23][0].rangehigh = 1.0f; sliders[23][0].value = 0.0f; // beard sliders[23][1].rangelow = 0.0f; sliders[23][1].rangehigh = 1.0f; sliders[23][1].value = 0.0f; // brow sliders[23][2].rangelow = 0.0f; sliders[23][2].rangehigh = 1.0f; sliders[23][2].value = 0.0f; // lids sliders[23][3].rangelow = 0.0f; sliders[23][3].rangehigh = 1.0f; sliders[23][3].value = 0.0f; // frizz tip // hair sliders[24][0].rangelow = 0.0f; sliders[24][0].rangehigh = 180.0f; sliders[24][0].value = 130.0f; // beard sliders[24][1].rangelow = 0.0f; sliders[24][1].rangehigh = 180.0f; sliders[24][1].value = 10.0f; // brow sliders[24][2].rangelow = 0.0f; sliders[24][2].rangehigh = 180.0f; sliders[24][2].value = 10.0f; // lids sliders[23][3].rangelow = 0.0f; sliders[23][3].rangehigh = 180.0f; sliders[23][3].value = 10.0f; for( x = 0; x < 5; x++ ) { sliders[25][x].value = 0.0f; sliders[25][x].rangehigh = 255.0f; sliders[25][x].rangelow = 0.0f; sliders[44][x].value = 0.0f; sliders[44][x].rangehigh = 900.0f; sliders[44][x].rangelow = 0.0f; sliders[45][x].value = 0.0f; sliders[45][x].rangehigh = 20.0f; sliders[45][x].rangelow = 0.0f; sliders[46][x].value = 1.0f; sliders[46][x].rangehigh = 2.0f; sliders[46][x].rangelow = 0.0f; sliders[41][x].value = 1.0f; sliders[41][x].rangehigh = 1.0f; sliders[41][x].rangelow = 0.0f; sliders[42][x].value = 0.0f; sliders[42][x].rangehigh = 1.0f; sliders[42][x].rangelow = 0.0f; } sliders[44][0].value = 0.0f; sliders[44][0].rangehigh = 1.0f; sliders[44][0].rangelow = 0.0f; sliders[44][4].value = 0.0f; sliders[44][4].rangehigh = 1.0f; sliders[44][4].rangelow = 0.0f; for( x = 0; x < 60; x++ ) { sliders[x][4].value = sliders[x][0].value; sliders[x][4].rangehigh = sliders[x][0].rangehigh; sliders[x][4].rangelow = sliders[x][0].rangelow; } sliders[3][4].value = 6.0f; sliders[0][4].value = 46.0f; sliders[8][4].rangelow = .05f; sliders[8][4].rangehigh = 1.0f; sliders[8][4].value = 1.0f; x = 43; sliders[43][0].value = 0.0f; sliders[43][4].value = 0.0f; sliders[44][0].value = 1.0f; sliders[44][4].value = 1.0f; sliders[45][0].value = 0.0f; sliders[45][4].value = 0.0f; sliders[46][0].value = 0.0f; sliders[46][4].value = 0.0f; sliders[47][0].value = 0.0f; // mess strength sliders[47][4].value = 0.0f; sliders[48][0].value = 0.0f;// flyaway strength sliders[48][4].value = 0.0f; sliders[49][0].value = 0.0f; // clumping strength sliders[49][4].value = 0.0f; sliders[50][0].value = 0.0f; // clump rotation strength sliders[50][4].value = 0.0f; sliders[51][0].value = 0.0f; // clump colors strength sliders[51][4].value = 0.0f; sliders[52][0].value = 0.0f; // clump rotation offset sliders[52][4].value = 0.0f; sliders[53][0].value = 0.0f; // clump rotation offset sliders[53][4].value = 0.0f; //Gclumps=0; } static void reset_dynamics( void ) { int x, y; for( x = 0; x < totalverts; x++ ) for( y = 0; y < 15; y++ ) { hair[x].velocity[y].x = 0; hair[x].velocity[y].y = 0; hair[x].velocity[y].z = 0; #ifdef LIB hair[x].lasthv[y] = hair[x].hv[y]; //this it? // thishair[x].hv[y]=hair[x].hv[y]; //this it? #endif } for( x = 0; x < total_splines; x++ ) for( y = 0; y < 15; y++ ) { Shairvelocity[x].hv[y].x = 0; Shairvelocity[x].hv[y].y = 0; Shairvelocity[x].hv[y].z = 0; // Shair[x].hv[y]=Sresthair[x].hv[y]; #ifdef LIB Slasthair[x].hv[y] = Shair[x].hv[y]; Sthishair[x].hv[y] = Shair[x].hv[y]; #endif } } void check_wmaps( void ) { int x, y; for( x = 0; x < 60; x++ ) { float totalv = 0; for( y = 0; y < totalverts; y++ ) { totalv += ( 1.0 - hair[y].slider[x] ); } // come back here // if (sliders[x][0].paint>=0) } } extern void MAYAwrite_hairDISK( char *hairfilename ) { RW_CONTEXT = RW_DISK; reset_rest( ); reset_hair( ); reset_faces( ); checkforzero( ); mkbounds( ); texture_bounds( ); weight_polys( ); write_hair( hairfilename ); } extern void MAYAread_hairMEM( MEMFILE * memfile, MEMFILE * memstat ) { OPENGL_DRAW = 0; RW_CONTEXT = RW_LOCAL; // if (slcheck()) { read_hair( memfile ); reset_rest( ); reset_faces( ); checkforzero( ); mkbounds( ); texture_bounds( ); weight_polys( ); if( memstat->data != NULL ) { free( memstat->data ); memstat->data = NULL; } //if (memfile->size>0) Nfree(memfile->data); RW_CONTEXT = RW_RESIZE; write_hair( memfile ); write_state_machine( memstat ); if( memfile->data != NULL ) { free( memfile->data ); memfile->data = NULL; } memfile->data = ( char * ) malloc( memfile->size * sizeof( char ) ); memstat->data = ( char * ) malloc( memstat->size * sizeof( char ) ); RW_CONTEXT = RW_LOCAL; write_hair( memfile ); write_state_machine( memstat ); RW_CONTEXT = RW_DISK; } // OPENGL_DRAW=1; } extern void MAYAread_hairDISK( char *hairfilename, MEMFILE * memfile, MEMFILE * memstat ) { OPENGL_DRAW = 0; RW_CONTEXT = RW_DISK; // if( slcheck( ) ) { read_hair( hairfilename ); reset_rest( ); reset_faces( ); checkforzero( ); mkbounds( ); texture_bounds( ); weight_polys( ); //if (memstat->size>0) Nfree(memstat->data); if( memfile->data != NULL ) { free( memfile->data ); memfile->data = NULL; } RW_CONTEXT = RW_RESIZE; write_hair( memfile ); write_state_machine( memstat ); if( memstat->data != NULL ) { free( memstat->data ); memstat->data = NULL; } memfile->data = ( char * ) malloc( memfile->size * sizeof( char ) ); memstat->data = ( char * ) malloc( memstat->size * sizeof( char ) ); RW_CONTEXT = RW_LOCAL; write_hair( memfile ); write_state_machine( memstat ); RW_CONTEXT = RW_DISK; } // OPENGL_DRAW=1; } static int startup = -1; // this deals with rest position only // MAYAdyn deals with dyanamics calc extern void MAYArefresh( CHNG *objfilename, MEMFILE * node, MEMFILE * node_state, SHAVEPARMS * shavep ) { int x; int y; int doneit = 0; // FILE *dg; //int hair_verts; int obj_verts = 0; char *stat = NULL; int oo; FILE *fp = NULL; FILE *fperr = NULL; //printf ("refresh\n");fflush(stdout); // dg = MYfopen ("c:\\temp.txt","w"); //fprintf (dg,"maxtest: mayarefresh1\n"); oo = OPENGL_DRAW; OPENGL_DRAW = 0; global_lastID = -1; lsSHAVEID = -1; //printf ("1\n");fflush(stdout); ///fperr=fopen("d:\\hello.txt","w"); for( x = 0; x < totalfaces; x++ ) { float big = 0; // int mtl; for( y = face_start[x]; y < face_end[x]; y++ ) { int g; g = facelist[y]; if( hair[g].restlength > 0 ) if( ( hair[g].mtl == head ) || ( hair[g].mtl == eyelash ) || ( hair[g].mtl == eyebrow ) || ( hair[g].mtl == splines ) || ( hair[g].mtl == beard ) ) { hair[g].pid = x; // resthair[g].pid=x; } } } //printf ("2\n");fflush(stdout); // if( slcheck( ) ) { //fprintf (dg,"maxtest: mayarefresh2\n"); if( node->data == NULL ) { global_lastID = -1; if( startup < 0 ) for( x = 0; x < 5; x++ ) { startup = 1; colmap[x].flags = 2; densemap[x].flags = 2; lenmap[x].flags = 2; colmap[x].r = NULL; colmap[x].g = NULL; colmap[x].b = NULL; colmap[x].a = NULL; lenmap[x].r = NULL; lenmap[x].g = NULL; lenmap[x].b = NULL; lenmap[x].a = NULL; densemap[x].r = NULL; densemap[x].g = NULL; densemap[x].b = NULL; densemap[x].a = NULL; } //printf ("3\n");fflush(stdout); //if (objfilename!=NULL) // fp=fopen(objfilename,"r"); //if (fp) // scan for verts //{ // char tmp[560]; // stat=fgets(tmp,555,fp); // while (stat!=NULL) // { // if ((tmp[0]=='v')&&(tmp[1]!='t')&&(tmp[1]!='n')&&(tmp[1]!='p')) // obj_verts++; // stat=fgets(tmp,555,fp); // } //fclose(fp); //} } if( objfilename == NULL ) { // printf ("restoring rest data\n"); if( node->data != NULL ) { RW_CONTEXT = RW_LOCAL; read_hair( node ); read_state_machine( node_state ); RW_CONTEXT = RW_DISK; #ifdef OLDCRAP RW_CONTEXT = RW_LOCAL; read_hair( node ); reset_dynamics( ); //for (x=0;x 0 ) // we have growth surfaces { // int fsize; node->size = 0; node->pos = 0; RW_CONTEXT = RW_RESIZE; // set_defaults(); //printf ("making rest data\n"); write_hair( node ); RW_CONTEXT = RW_DISK; { long fsize = 0; fsize = node->size; if( node->data != NULL ) { free( node->data ); node->data = NULL; } if( fsize > 0 ) { node->data = ( char * ) malloc( fsize ); // +1 node->size = ( long ) ( fsize ); // +1 node->pos = ( long ) 0; node->time = gt; } } node_state->size = 0; node_state->pos = 0; node->time = gt; RW_CONTEXT = RW_RESIZE; // set_defaults(); write_state_machine( node_state ); RW_CONTEXT = RW_DISK; { long fsize = 0; // char tmps[255]; // short junks; // fp = fopen("tmp1024.hair", "rb"); // if (fp) // { // fseek(fp, 0, SEEK_END); // fsize = ftell(fp); // fclose(fp); // } fsize = node_state->size; // +1 //printf("fsize= %d\n",fsize); //printf ("5\n");fflush(stdout); if( node_state->data != NULL ) { free( node_state->data ); node_state->data = NULL; } if( fsize > 0 ) { node_state->data = ( char * ) malloc( fsize ); // +1 node_state->size = ( long ) ( fsize ); // +1 node_state->pos = ( long ) 0; } } } } RW_CONTEXT = RW_DISK; // printf ("done.\n"); #endif } else { //printf("no node data\n"); doneit = 1; } // printf ("restoring rest state\n"); if( node_state->data != NULL ) { RW_CONTEXT = RW_LOCAL; ////read_state_machine(node_state); // printf ("done.\n"); RW_CONTEXT = RW_DISK; } else { //printf("no node_state data\n"); doneit = 1; } doneit = 1; } //if (node) if( node != NULL ) if( doneit == 0 ) { //printf ("6\n");fflush(stdout); if( ( node->data == NULL ) ) // no hairfile ! { Dtotalverts = 0; SHAVEclear_stack( ); SHAVEclear_scene(); //fprintf (dg,"maxtest: mayarefresh3\n"); //printf ("getting obj %s\n",objfilename); getobj( objfilename ); // flip //fprintf (dg,"maxtest: totalverts = %d\n",totalverts); reset_rest( ); reset_noisespace( ); set_defaults( ); shavep->collision_method = COLLISION_METHOD; reset_faces( ); init_noise( ); { int yy; // for (x=0;x 0 ) // we have growth surfaces { // int fsize; node->size = 0; node->pos = 0; RW_CONTEXT = RW_RESIZE; // set_defaults(); //printf ("making rest data\n"); //fprintf (dg,"maxtest: mayarefresh4\n"); write_hair( node ); RW_CONTEXT = RW_DISK; { long fsize = 0; fsize = node->size; if( node->data != NULL ) { free( node->data ); node->data = NULL; } if( fsize > 0 ) { node->data = ( char * ) malloc( fsize ); // +1 node->size = ( long ) ( fsize ); // +1 node->pos = ( long ) 0; } } node_state->size = 0; node_state->pos = 0; RW_CONTEXT = RW_RESIZE; // set_defaults(); write_state_machine( node_state ); RW_CONTEXT = RW_DISK; { long fsize = 0; // char tmps[255]; // short junks; // fp = fopen("tmp1024.hair", "rb"); // if (fp) // { // fseek(fp, 0, SEEK_END); // fsize = ftell(fp); // fclose(fp); // } fsize = node_state->size; // +1 //printf("fsize= %d\n",fsize); if( node_state->data != NULL ) { free( node_state->data ); node_state->data = NULL; } if( fsize > 0 ) { node_state->data = ( char * ) malloc( fsize ); // +1 node_state->size = ( long ) ( fsize ); // +1 node_state->pos = ( long ) 0; } } //printf ("8\n");fflush(stdout); node_state->time = gt; node->time = gt; reset_rest( ); reset_noisespace( ); reset_faces( ); init_noise( ); reset_faces( ); checkforzero( ); mkbounds( ); texture_bounds( ); weight_polys( ); node->pos = 0; node_state->pos = 0; RW_CONTEXT = RW_LOCAL; write_hair( node ); write_state_machine( node_state ); RW_CONTEXT = RW_DISK; node->pos = 0; node_state->pos = 0; } shavep->multrot=0.0f; shavep->multrot_phase=0.0f; shavep->multrot_offset=0.0f; shavep->tipfade=1; for( x = 0; x < 5; x++ ) { shavep->frizz_anim_dir[x] = Ganim_dir[x]; shavep->passes[x] = LOCAL_PASSES[x]; shavep->haircount[x] = LOCAL_CNT[x]; shavep->shadowHaircount[x] = LOCAL_SHADCNT[x]; shavep->segs[x] = LOCAL_SEGS[x]; for( y = 0; y < 60; y++ ) { shavep->slider_val[y][x] = sliders[y][x].value; // sprintf( shavep->slider_lable[y][x], "%s", sliders[y][x].lable ); // shavep->painted[y][x] = sliders[y][x].paint; } } shavep->slider_val[0][5] = sliders[0][5].value; sprintf( shavep->slider_lable[0][5], "gravity" ); shavep->painted[0][5] = 0; if( total_splines == 0 ) shavep->total_guides = totalverts; else shavep->total_guides = total_splines; shavep->instancing_status = 0; //shavep->use_old_splayscale=0; //++ shavep->dontinterpolate = 0; sprintf( shavep->name, "BLANK" ); if( freeze.totalverts > 0 ) shavep->instancing_status = 1; //printf ("9\n");fflush(stdout); if( totalverts == 0 ) if( total_splines == 0 ) { printf( "*** ERROR *** create_hair failed\n" ); // SHAVEclear_stack( ); // SHAVEcleanup( ); } } else // do we have a hair file? { // at this point we do have a hairfile RW_CONTEXT = RW_LOCAL; // printf("hey, I shouldn't be in maya refresh\n"); node->pos = 0; read_hair( node ); node->pos = 0; //for (x=0;xpos=0; //read_state_machine(node_state); //node_state->pos=0; RW_CONTEXT = RW_DISK; reset_faces( ); checkforzero( ); reset_faces( ); init_noise( ); reset_faces( ); checkforzero( ); mkbounds( ); texture_bounds( ); weight_polys( ); RW_CONTEXT = RW_LOCAL; node->pos = 0; write_hair( node ); node->pos = 0; node_state->pos = 0; write_state_machine( node_state ); node_state->pos = 0; RW_CONTEXT = RW_DISK; } if( totalverts + total_splines > 0 ) { // STRANDNfree(ret); // MAYAalloc(ret); // allocate a strand } } // doneit==0 //OPENGL_DRAW=1; //if (fperr) fclose(fperr); } // slcheck //printf ("done\n"); // fprintf (dg,"maxtest: mayarefresh5\n"); global_lastID = -1; //printf ("end refresh\n");fflush(stdout); //fclose(dg); } extern void MAYAxform2( WFTYPE * objfile, MEMFILE * node, MEMFILE * node_state, int run_dyn, CHNG *stat, SHAVEPARMS * shavep ) { //int hair_verts; int obj_verts = 0; int iv; int oo; int fastmode = 0; //char statfile[255]; //FILE *fp; if( run_dyn == 1 ) Grendermode = 0; else Grendermode = 1; Gdynamics_mode = run_dyn; oo = OPENGL_DRAW; OPENGL_DRAW = 0; SHAVEID = (unsigned long) node->ID; // MAYAset_parms( shavep ); // fprintf(stdout,"ID = %d clumps = %d mayaxform2\n",SHAVEID,Gclumps);fflush(stdout); SHAVEID = (unsigned long) node->ID; if( global_lastID != -1 ) if( SHAVEID == global_lastID ) //xcxcxc if( SHAVEID == ( int ) global_lastID ) fastmode = 1; if( run_dyn > 0 ) fastmode = 0; if( run_dyn < 0 ) fastmode = 0; //#ifndef EXTERNAL_COLLISION fastmode = 0; // for jerome ! //#endif if( node ) if( node->data == NULL ) fastmode = 0; if( node_state ) if( node_state->data == NULL ) fastmode = 0; if( node == NULL ) fastmode = 0; if( node_state == NULL ) fastmode = 0; //#ifndef EXTERNAL_COLLISION //fastmode=0; //#endif if( fastmode == 0 ) global_lastID = -1; // if (node->data==NULL) // printf ("MAYAxform :hey man, this MEMfile is NULL! check the dongle"); if( node ) if( objfile->v ) if( node->data ) // do we have a hair file? { // at this point we do have a hairfile int x; //printf ("before:\n"); //printf ("Dtotalverts = %d\n",Dtotalverts); //for (x=0;x<5;x++) //printf ("LOCAL_HAIRCOUNT[%d]= %d\n",x,LOCAL_CNT[x]); /// restore the node to shave memory RW_CONTEXT = RW_LOCAL; node->pos = 0; #ifndef EXTERNAL_COLLISION //fastmode=0; #endif //fastmode=0; SHAVEID = node->ID; if( fastmode == 0 ) read_hair( node ); if( fastmode == 1 ) { int y; //read_hair(node); SHAVEID = node->ID; read_hairFAST( node ); //read_hair(node); } SHAVEID = (unsigned long) node->ID; MAYAset_parms( shavep ); // fprintf(stdout,"ID = %d clumps = %d shavexforms\n",SHAVEID,Gclumps);fflush(stdout); node->pos = 0; gt = node_state->time; if (total_splines<=0) if( objfile != NULL ) if( objfile->totalverts != Dtotalverts ) { if( undo ) free( undo ); undo = NULL; if( Sundo ) free( Sundo ); Sundo = NULL; undo_totalverts = -1; Sundo_totalverts = -2; fprintf( stdout, "number of verts going to xform2 don't match shave engine! external expectation %d actual engine %d\n", objfile->totalverts, Dtotalverts ); fflush( stdout ); } if( total_splines > 0 ) { int yy; for( x = 0; x < total_splines; x++ ) for( yy = 0; yy < 15; yy++ ) Shair[x].noisev[yy] = Sresthair[x].noisev[yy]; } if( total_splines > 0 ) for( x = 0; x < total_splines; x++ ) { memcpy( &Sresthair[x], &Shair[x], sizeof( BASEHAIR ) ); } if( node_state ) if( run_dyn == 1 ) { node_state->pos = 0; read_state_machine( node_state ); node_state->pos = 0; // gt++; // node_state->time = gt; } if( objfile->totalverts == Dtotalverts ) if( total_splines == 0 ) if( totalverts > 0 ) for( x = 0; x < totalverts; x++ ) if( hair[x].select[0] ) { iv = vlink[x]; hair[x].uu = objfile->uv[iv].x; hair[x].vv = objfile->uv[iv].y; hair[x].uu = objfile->uv[iv].x; hair[x].vv = objfile->uv[iv].y; } if( objfile->totalverts == Dtotalverts ) if( total_splines > 0 ) for( x = 0; x < total_splines; x++ ) { iv = Dface_start[x]; // should this be vlink? // we're assumine splines are -first- Sresthair[x].uu = objfile->uv[iv].x; Sresthair[x].vv = objfile->uv[iv].y; Shair[x].uu = objfile->uv[iv].x; Shair[x].vv = objfile->uv[iv].y; } RW_CONTEXT = RW_DISK; //printf ("after:\n"); //printf ("Dtotalverts = %d\n",Dtotalverts); //for (x=0;x<5;x++) //printf ("LOCAL_HAIRCOUNT[%d]= %d\n",x,LOCAL_CNT[x]); if( fastmode == 0 ) { //optimise init_noise( ); //optimise reset_faces( ); //optimise checkforzero( ); //optimise mkbounds( ); //optimise texture_bounds( ); //optimise weight_polys( ); } ///// //printf ("resthair[0].x=%f\n",resthair[0].hv[0].x); //if (Dv==NULL) printf ("hey Dv has been cleared somewhere!"); if( objfile->totalverts == Dtotalverts ) // if( run_dyn != 2 ) { if( Dtotalverts == objfile->totalverts ) for( x = 0; x < Dtotalverts; x++ ) { Dv[x].x = objfile->v[x].x; Dv[x].y = objfile->v[x].y; Dv[x].z = -objfile->v[x].z; //flip if( Dtag[x] ) { v[Dlink[x]] = Dv[x]; } } make_normals( ); //if (objfile->totalverts==Dtotalverts) xformcontrolhair( ); //if (run_dyn==0) if( objfile->totalverts == Dtotalverts ) { int y; if( total_splines > 0 ) for( y = 0; y < 15; y++ ) for( x = 0; x < total_splines; x++ ) { Shair[x].velocity[y].x = Shair[x].hv[y].x - Slasthair[x].hv[y].x; Shair[x].velocity[y].y = Shair[x].hv[y].y - Slasthair[x].hv[y].y; Shair[x].velocity[y].z = Shair[x].hv[y].z - Slasthair[x].hv[y].z; } // if (total_splines>0) // for (x=0;xtime = 0; } if( ( run_dyn == 1 ) ) //||(run_dyn == -1)) ////if (stat!=NULL) doframe( ); RW_CONTEXT = RW_DISK; if( stat != NULL ) if( ( run_dyn == 1 ) ) //||(run_dyn== -1)) write_state( stat ); if( stat != NULL ) if( run_dyn == 2 ) read_state( stat ); RW_CONTEXT = RW_LOCAL; // dec16 if (run_dyn!=2) // dec16 if (run_dyn!=0) { // jan 3 if ((run_dyn<1)||(run_dyn==2)) { for( x = 0; x < totalverts; x++ ) // if (hair[x].select[0]) //if ((hair[x].select[0])||(Gdynamics_mode!=0)) { memcpy( &hair[x].lasthv, &hair[x].hv, sizeof( VERT ) * 15 ); } for( x = 0; x < total_splines; x++ ) memcpy( &Sthishair[x], &Shair[x], sizeof( BASEHAIR ) ); for( x = 0; x < total_splines; x++ ) memcpy( &Slasthair[x], &Shair[x], sizeof( BASEHAIR ) ); } } { node->pos = 0; } RW_CONTEXT = RW_DISK; } if( !node_state ) { fprintf( stderr, "xform2:statMEM is NULL - can't write to it\n" ); } if( !node ) { fprintf( stderr, "xform2:restMEM is NULL - can't read from it\n" ); } if( node_state ) if( ( fastmode == 0 ) || ( node_state->data == NULL ) ) if( node_state->data != NULL ) { free( node_state->data ); node_state->data = NULL; } if( node_state ) if( ( fastmode == 0 ) || ( node_state->data == NULL ) ) //if (node_state->data==NULL) { node_state->pos = 0; node_state->size = 0; RW_CONTEXT = RW_RESIZE; write_state_machine( node_state ); if( node_state->data != NULL ) { free( node_state->data ); node_state->data = NULL; } node_state->data = ( char * ) malloc( node_state->size * sizeof( char ) ); } if( node_state ) { RW_CONTEXT = RW_LOCAL; node_state->pos = 0; write_state_machine( node_state ); node_state->time = gt; } SHAVEID = (unsigned long) node->ID; MAYAset_parms( shavep ); #ifdef diagnose_trouble fprintf(stdout,"ID = %d clumps = %d shavexforms\n",SHAVEID,Gclumps);fflush(stdout); #endif //OPENGL_DRAW=1; //xcxcxcxc SHAVEID = (int )node->ID; SHAVEID = (unsigned long) node->ID; //#ifdef crap //printf ("select = %d ", // hair[5].select[14]); //#endif global_lastID = SHAVEID; node_state->time = gt; node->time = gt; //optimise make_normals( ); // RW_CONTEXT=RW_DISK; xformHandles( ); } static float dot( VERT a, VERT b ) { float ret; ret = a.x * b.x + a.y * b.y + a.z * b.z; return ( ret ); } static void free_depth( void ) { } #include "lotswf.c" #include "lotswfROOT.c" //#include "lotswf2.c" #include void read_targa( CHNG filename[255], TGABUFF * tbuff ) { unsigned char header[18]; int width, height, widthSample, heightSample; int topDown, cmlen; int x, y; int quit = 0; int r, g, b; int sampleX, sampleY; FILE *tgaFile = NULL, *outFile; FILE *fp = NULL; char tmp[255]; tgaFile = NULL; outFile = NULL; fp = MYfopen( filename, _T("rb") ); if( fp == NULL ) { sprintf( tmp, "Cannot open image '%s'.", filename ); if( GLOBAL_VERBOSE ) printf( "%s\n", tmp ); quit = 1; // exit(1); } else if( fp != NULL ) fclose( fp ); while( quit == 0 ) { if( ( tgaFile = MYfopen( filename, _T("rb") ) ) ) fread( header, sizeof( unsigned char ), 18, tgaFile ); if( header[2] < 1 && header[2] > 3 ) // not straight raster! { sprintf( tmp, "Not a raster-based Targa file.\n" ); if( GLOBAL_VERBOSE ) printf( "%s", tmp ); quit = 1; if( tgaFile != NULL ) fclose( tgaFile ); } if( header[16] != 24 ) // not 24bpp! { sprintf( tmp, "Expecting color depth of 24 bits in Targa file; found %d.\n", ( int ) header[16] ); if( GLOBAL_VERBOSE ) printf( "%s", tmp ); fclose( tgaFile ); // exit(1); quit = 1; } if( quit == 0 ) if( tgaFile != NULL ) { width = header[13] * 256 + header[12]; widthSample = 1; height = header[15] * 256 + header[14]; heightSample = 1; //if (tbuff->width >0) //{ // free(tbuff->r); // free(tbuff->g); // free(tbuff->b); // tbuff->width=0; // tbuff->height=0; //} if( ( width > 0 ) && ( height > 0 ) ) { tbuff->r = ( unsigned char * ) malloc( ( width + 1 ) * ( height + 1 ) * sizeof( unsigned char ) ); tbuff->g = ( unsigned char * ) malloc( ( width + 1 ) * ( height + 1 ) * sizeof( unsigned char ) ); tbuff->b = ( unsigned char * ) malloc( ( width + 1 ) * ( height + 1 ) * sizeof( unsigned char ) ); if( tbuff->b == NULL ) { DRAW_STATUS( "Not enough memory for textures" ); free_maps( ); width = 0; height = 0; Glow_mem = 1; } tbuff->width = width; tbuff->height = height; } topDown = 0; // bottom-up raster if( ( header[17] & 0x20 ) ) // top-down raster topDown = 1; if( header[0] > 0 ) fseek( tgaFile, header[0], SEEK_CUR ); // skip over picture ID info cmlen = header[6] * 256 + header[5]; if( cmlen > 0 ) { int cmsize = header[7] / 8; fseek( tgaFile, cmlen * cmsize, SEEK_CUR ); // ignore color map } sampleX = 0; // (topDown ? 0 : thumbHeight); sampleY = 0; for( y = 0; y < height; y++ ) for( x = 0; x < width; x++ ) { tbuff->r[x + width * y] = ( unsigned char ) 0; tbuff->g[x + width * y] = ( unsigned char ) 0; tbuff->b[x + width * y] = ( unsigned char ) 0; } for( x = 0; x < height; x++ ) { for( y = 0; y < width; y++ ) { b = ( int ) getc( tgaFile ); g = ( int ) getc( tgaFile ); r = ( int ) getc( tgaFile ); tbuff->r[y + width * x] = ( unsigned char ) r; tbuff->g[y + width * x] = ( unsigned char ) g; tbuff->b[y + width * x] = ( unsigned char ) b; } } sprintf( tbuff->name, "%s", filename ); if( tgaFile ) fclose( tgaFile ); } quit = 1; } } #include #include static void read_animated_targa( char filename[255], TGABUFF * tbuff ) { int x; int cons = 0; char outfile[255]; char tmpfile[255]; int start1 = 0; int end1 = 0; int ln; ln = strlen( filename ); for( x = 0; x < ln; x++ ) { if( cons > 0 ) if( ( filename[x] >= 48 ) && ( filename[x] <= 57 ) ) if( ( filename[x - 1] >= 48 ) && ( filename[x - 1] <= 57 ) ) { cons++; end1 = x; } // if ((filename[x]>=48) && (filename[x]<=57)) if( cons > 0 ) if( cons < 4 ) if( ( filename[x] < 48 ) || ( filename[x] > 57 ) ) { cons = 0; } if( cons == 0 ) if( ( filename[x] >= 48 ) && ( filename[x] <= 57 ) ) { start1 = x; cons++; } } sprintf( outfile, "%s", filename ); // it's a still? #ifdef LIB if( cons == 4 ) // there is a 4pad number in there { char tm[5]; { sprintf( tm, "%04d", GlobalTime ); for( x = 0; x < start1; x++ ) tmpfile[x] = filename[x]; for( x = start1; x <= end1; x++ ) tmpfile[x] = tm[x - start1]; for( x = end1 + 1; x <= ln; x++ ) tmpfile[x] = filename[x]; // ok, so we've replaced the 4pad with the current time } //sprintf(outfile,"%s",tmpfile); //{ // FILE *fp; // fp=fopen("test.txt","w"); // fprintf(fp,"%s\n",tmpfile); // fprintf (fp,"tm %s original %s start1 %d end1 %d const %d\n",tm,filename,start1,end1,cons); // fclose(fp); //} if( Jexists( tmpfile ) == 1 ) // there's no file by this name { sprintf( outfile, "%s", tmpfile ); } } // end there's a 4 pad #endif read_targa( outfile, tbuff ); } void MAYAwrite_targa( CHNG *filename, short width, short height, unsigned char *image ) { unsigned char header[18]; int x, y; FILE *tgaFile = NULL; short Swidth, Sheight; Swidth = width; Sheight = height; tgaFile =(FILE*) MYfopen( filename, _T("wb") ); if( tgaFile == NULL ) printf( "could not open %s for output\n", filename ); if( tgaFile != NULL ) // cross it out with red if( !slcheck( ) ) { for( x = 0; x < width; x++ ) { int add; int y; y = ( short ) ( ( float ) x * ( ( float ) height / ( float ) width ) ); add = x * 4 + width * 4 * y; image[add] = 255; } for( x = 0; x < width; x++ ) { int add; int y; y = ( short ) ( ( ( float ) width - ( float ) x ) * ( ( float ) height / ( float ) width ) ); add = x * 4 + width * 4 * y; image[add] = 255; } } if( tgaFile != NULL ) { unsigned char abyte; for( x = 0; x < 12; x++ ) header[x] = 0; header[2] = 2; // straight raster? fwrite( &header, sizeof( unsigned char ), 12, tgaFile ); SHAVE_SWAB2( &Swidth ); SHAVE_SWAB2( &Sheight ); fwrite( &Swidth, 1, 2, tgaFile ); // write X size fwrite( &Sheight, 1, 2, tgaFile ); // Y size abyte = 32; fwrite( &abyte, 1, 1, tgaFile ); // BPP abyte = 8; // pixel format : if tga depth is 24 bits set to 0, 8 for 32bpp fwrite( &abyte, 1, 1, tgaFile ); // pixel format if( GLOBAL_VERBOSE ) printf( "writing image data\n" ); for( y = 0; y < height; y++ ) { for( x = 0; x < width; x++ ) { int add; char r, g, b, a; add = x * 4 + y * width * 4; b = ( char ) image[add]; g = ( char ) image[add + 1]; r = ( char ) image[add + 2]; a = ( char ) image[add + 3]; putc( r, tgaFile ); putc( g, tgaFile ); putc( b, tgaFile ); putc( a, tgaFile ); } } fclose( tgaFile ); } } //fwrite(data,sizeX*sizeY,3,tga); // pixel data static void Gilluminate_strand( WFTYPE * pos, int ll, float hambient ) { VERT ret; VERT pos2; VERT lcolor; VERT drr; VERT lookvec; int q, x; float cone = 1.0f; ret.x = 0.0f; ret.y = 0.0f; ret.z = 0.0f; for( q = 0; q < pos->totalverts; q++ ) { VERT shad; lcolor = LWlight[ll].color; if( LWlight[ll].trace == 0 ) { cone = calculate_light_cone( pos->v[q], ll, Gbacklighting, &pos->velocity[q] /* get the raw cone */ ); if( LWlight[ll].xres == 0 ) cone = 1.0f; } else { cone = 1.0f; } pos->color[q] = lcolor; } for( x = 0; x < pos->totalverts; x++ ) pos->v[x].z *= -1; for( x = 0; x < pos->totalverts; x++ ) SHAVEcoord_convertFROMSHAVE( &pos->v[x] ); if( DOING_SWATCH == 0 ) SHAVEapply_illuminationWF( ll, pos ); for( x = 0; x < pos->totalverts; x++ ) SHAVEcoord_convertTOSHAVE( &pos->v[x] ); for( x = 0; x < pos->totalverts; x++ ) pos->v[x].z *= -1; for( q = 0; q < pos->totalverts; q++ ) { lcolor = pos->color[q]; cone = pos->velocity[q].x; if( LWlight[ll].trace == 0 ) { if( cone > 0.0f ) // speed consequences here if( LWlight[ll].xres > 0 ) ret = cast_shadows_lgt_simple( pos->v[q], ll ); else { ret.x = 1.0f; ret.y = 1.0f; ret.z = 1.0f; } } else if( LWlight[ll].trace == 1 ) if( cone > 0.0f ) ret = cast_shadows_lgt_simple( pos->v[q], ll); { ret.x *= hambient; ret.y *= hambient; ret.z *= hambient; ret.x += ( 1.0f - hambient ); ret.y += ( 1.0f - hambient ); ret.z += ( 1.0f - hambient ); } ret.x *= lcolor.x * cone; ret.y *= lcolor.y * cone; ret.z *= lcolor.z * cone; // ret.x=lcolor.x*cone; // testing the light cone // ret.y=lcolor.x*cone; // ret.z=lcolor.x*cone; pos->color[q] = ret; } } extern void SHAVEsplinelock_clear(SHAVENODE *sn ) { MAYAflush_state(&sn->restMEM,&sn->statMEM); // load node into engine Gtotal_splinelocks= 0; free_MEMFILE( &sn->restMEM ); free_MEMFILE( &sn->statMEM ); global_lastID = -1; MAYAfetch_node( &sn->restMEM, &sn->statMEM, &sn->shavep ); // replace the node } void SHAVEsustained_spline_recomb( SHAVENODE * sn, WFTYPE * wf ) { int clfID1 = -1, clfID2 = -1, clfID3 = -1; int clptID1 = -1, clptID2 = -1, clptID3 = -1; float clptd1, clptd2, clptd3; int x, y; float d = -1.0f, cld = -1.0f; int clid = -1; SHAVEPARMS tempmat; SHAVEID = sn->restMEM.ID; MAYAflush_state(&sn->restMEM,&sn->statMEM); // load node into engine MAYAset_parms( &sn->shavep ); #ifdef diagnose_trouble fprintf(stdout,"ID = %d clumps = %d sustained_spline\n",SHAVEID,Gclumps);fflush(stdout); #endif for( x = 0; x < wf->totalverts; x++ ) { wf->v[x].z *= -1.0f; // should be flipped } // SHAVEreplace_rest( sn ); // not sure if I need this // if( Guse_restlength == 0 ) // re_param_splines( wf ); // reparameterise curves //else // for( x = 0; x < wf->totalverts; x++ ) // { // wf->v[x].z *= -1.0f; // should be flipped // } //put_geomWF(wf,"c:\\splines_after.obj"); for( x = 0; x < totalverts; x++ ) // cycle through the guides if( hair[x].restlength != 0 ) // ok, find the 3 closest splines { VERT vvroot; VERT vva, vvb, vvc; //ok so, at this point we have a bary point, we can // stuff the spline's values into the guide vva = wf->v[hair[x].Bid1 ]; vvb = wf->v[hair[x].Bid2 ]; vvc = wf->v[hair[x].Bid3 ]; vvroot.x=vva.x*hair[x].bw1+vvb.x*hair[x].bw2 + vvc.x *hair[x].bw3; vvroot.y=vva.y*hair[x].bw1+vvb.y*hair[x].bw2 + vvc.y *hair[x].bw3; vvroot.z=vva.z*hair[x].bw1+vvb.z*hair[x].bw2 + vvc.z *hair[x].bw3; for( y = 1; y < 15; y++ ) // we're assuming 15 verts { vva = wf->v[hair[x].Bid1 + y]; vvb = wf->v[hair[x].Bid2 + y]; vvc = wf->v[hair[x].Bid3 + y]; { hair[x].hv[y].x = vva.x * hair[x].bw1 + vvb.x * hair[x].bw2 + vvc.x * hair[x].bw3; hair[x].hv[y].y = vva.y * hair[x].bw1 + vvb.y * hair[x].bw2 + vvc.y * hair[x].bw3; hair[x].hv[y].z = vva.z * hair[x].bw1 + vvb.z * hair[x].bw2 + vvc.z * hair[x].bw3; } hair[x].hv[y].x -= vvroot.x - hair[x].hv[0].x; hair[x].hv[y].y -= vvroot.y - hair[x].hv[0].y; hair[x].hv[y].z -= vvroot.z - hair[x].hv[0].z; // hair[x].resthv[y] = hair[x].hv[y]; // hair[x].noisev[y] = hair[x].hv[y]; } } for( x = 0; x < wf->totalverts; x++ ) { wf->v[x].z *= -1.0f; // should be flipped } free_MEMFILE( &sn->restMEM ); free_MEMFILE( &sn->statMEM ); global_lastID = -1; MAYAfetch_node( &sn->restMEM, &sn->statMEM, &tempmat ); // replace the node } void SHAVEsplinelock_set( SHAVENODE * sn, WFTYPE * wf ) { int clfID1 = -1, clfID2 = -1, clfID3 = -1; int clptID1 = -1, clptID2 = -1, clptID3 = -1; float clptd1, clptd2, clptd3; int x, y; float d = -1.0f, cld = -1.0f; int clid = -1; BARYVERT bv[910]; SHAVEPARMS tempmat; SHAVEID = sn->restMEM.ID; MAYAflush_state(&sn->restMEM,&sn->statMEM); // load node into engine MAYAset_parms( &sn->shavep ); #ifdef diagnose_trouble fprintf(stdout,"ID = %d clumps = %d splinelock_set\n",SHAVEID,Gclumps);fflush(stdout); #endif for( x = 0; x < wf->totalverts; x++ ) { wf->v[x].z *= -1.0f; // should be flipped } // put_geomWF( wf, "c:\\splines_before.obj" ); // if( Guse_restlength == 0 ) // re_param_splines( wf ); // reparameterise curves // else // for( x = 0; x < wf->totalverts; x++ ) // { // wf->v[x].z *= -1.0f; // should be flipped // } Gtotal_splinelocks=wf->totalverts; //put_geomWF(wf,"c:\\splines_after.obj"); for( x = 0; x < wf->totalverts; x++ ) wf->velocity[x].x = 0; for( x = 0; x < wf->totalverts; x++ ) wf->velocity[x].y = 0; // tag the end verts for( x = 0; x < wf->totalfaces; x++ ) { wf->velocity[wf->face_start[x]].x = 1; wf->velocity[wf->face_start[x]].y = ( float ) x; } for( x = 0; x < totalverts; x++ ) // cycle through the guides // if( hair[x].restlength != 0 ) // ok, find the 3 closest splines { { clptID1 = -1; clptID2 = -1; clptID3 = -1; clptd1 = 1000000.0f; clptd2 = 1000000.0f; clptd3 = 1000000.0f; for( y = 0; y < wf->totalverts; y++ ) if( wf->velocity[y].x != 0 ) // it's an end point { float dx, dy, dz; dx = wf->v[y].x - hair[x].hv[0].x; dy = wf->v[y].y - hair[x].hv[0].y; dz = wf->v[y].z - hair[x].hv[0].z; d = sqrt( dx * dx + dy * dy + dz * dz ); if( d < clptd1 ) // push points { clptd3 = clptd2; clptd2 = clptd1; clfID3 = clfID2; clfID2 = clfID1; clptID3 = clptID2; clptID2 = clptID1; clptID1 = y; clptd1 = d; clfID1 = ( int ) wf->velocity[y].y; // we've stuffed the face ID in here } else if( d < clptd2 ) // push points { clptd3 = clptd2; clfID3 = clfID2; clptID3 = clptID2; clptID2 = y; clptd2 = d; clfID2 = ( int ) wf->velocity[y].y; // we've stuffed the face ID in here } else if( d < clptd3 ) // push points { clptID3 = y; clptd3 = d; clfID3 = ( int ) wf->velocity[y].y; // we've stuffed the face ID in here } } } if( clptID2 == -1 ) { clptID2 = clptID1; clptd2 = clptd1; clfID2 = clfID1; } if( clptID3 == -1 ) { clptID3 = clptID2; clptd3 = clptd2; clfID3 = clfID2; } // now, we want to scatter some points with barycentric weights for( y = 0; y < 896; y++ ) { float s, t; float a, b, c; s = ( float ) drand98( ); //MTmix100(gs); t = ( float ) drand98( ); if( s + t > 1 ) { s = 1 - s; t = 1 - t; } a = s; b = t; c = ( 1 - s - t ); bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; } { float a, b, c; a = 1.0f; b = 0.0f; c = 0.0f; y = 896; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; a = 0.0f; b = 1.0f; c = 0.0f; y = 897; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; a = 0.0f; b = 0.0f; c = 1.0f; y = 898; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; a = 0.0f; b = 0.0f; c = 1.0f; y = 899; bv[y].b1 = a; bv[y].b2 = b; bv[y].b3 = c; bv[y].p.x = wf->v[clptID1].x * a + wf->v[clptID2].x * b + wf->v[clptID3].x * c; bv[y].p.y = wf->v[clptID1].y * a + wf->v[clptID2].y * b + wf->v[clptID3].y * c; bv[y].p.z = wf->v[clptID1].z * a + wf->v[clptID2].z * b + wf->v[clptID3].z * c; } // now, let's pick the closest one to the guide root { VERT gr; gr = hair[x].hv[0]; cld = 10000000.0f; for( y = 0; y < 899; y++ ) { float dx, dy, dz; dx = gr.x - bv[y].p.x; dy = gr.y - bv[y].p.y; dz = gr.z - bv[y].p.z; d = ( float ) sqrt( dx * dx + dy * dy + dz * dz ); if( d < cld ) { cld = d; clid = y; } } } //ok so, at this point we have a bary point, we can //printf ("clid = %d cld=%f\n",clid,cld); // stuff the spline's values into the guide { VERT vvroot; VERT vva, vvb, vvc; hair[x].Bid1=clptID1; hair[x].Bid2=clptID2; hair[x].Bid3=clptID3; hair[x].bw1=bv[clid].b1; hair[x].bw2=bv[clid].b2; hair[x].bw3=bv[clid].b3; vva = wf->v[hair[x].Bid1 ]; vvb = wf->v[hair[x].Bid2 ]; vvc = wf->v[hair[x].Bid3 ]; vvroot.x=vva.x*hair[x].bw1+vvb.x*hair[x].bw2 + vvc.x *hair[x].bw3; vvroot.y=vva.y*hair[x].bw1+vvb.y*hair[x].bw2 + vvc.y *hair[x].bw3; vvroot.z=vva.z*hair[x].bw1+vvb.z*hair[x].bw2 + vvc.z *hair[x].bw3; for( y = 1; y < 15; y++ ) // we're assuming 15 verts { vva = wf->v[clptID1 + y]; vvb = wf->v[clptID2 + y]; vvc = wf->v[clptID3 + y]; //if (cld!=0) { hair[x].hv[y].x = vva.x * bv[clid].b1 + vvb.x * bv[clid].b2 + vvc.x * bv[clid].b3; hair[x].hv[y].y = vva.y * bv[clid].b1 + vvb.y * bv[clid].b2 + vvc.y * bv[clid].b3; hair[x].hv[y].z = vva.z * bv[clid].b1 + vvb.z * bv[clid].b2 + vvc.z * bv[clid].b3; } // hair[x].hv[y].x -= bv[clid].p.x - hair[x].hv[0].x; // hair[x].hv[y].y -= bv[clid].p.y - hair[x].hv[0].y; // hair[x].hv[y].z -= bv[clid].p.z - hair[x].hv[0].z; hair[x].hv[y].x -= vvroot.x - hair[x].hv[0].x; hair[x].hv[y].y -= vvroot.y - hair[x].hv[0].y; hair[x].hv[y].z -= vvroot.z - hair[x].hv[0].z; hair[x].resthv[y] = hair[x].hv[y]; hair[x].noisev[y] = hair[x].hv[y]; } } //re_param_base(&hair[x]); // if (Guse_restlength!=1) if( 0 == 1 ) { hair[x].restlength = Distance( hair[x].hv[2], hair[x].hv[3] ); hair[x].restlength += Distance( hair[x].hv[7], hair[x].hv[8] ); hair[x].restlength += Distance( hair[x].hv[12], hair[x].hv[13] ); hair[x].restlength /= 3.0f; } } for( x = 0; x < wf->totalverts; x++ ) { wf->v[x].z *= -1.0f; // should be flipped } free_MEMFILE( &sn->restMEM ); free_MEMFILE( &sn->statMEM ); global_lastID = -1; MAYAfetch_node( &sn->restMEM, &sn->statMEM, &tempmat ); // replace the node // printf ("this is a 3.0 function - under construction..\n");fflush(stdout); }