// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 extern void SHAVEallocate_kernal(MINIKERNAL *in,SHAVEPARMS *shavep,int count, int segs); extern void SHAVEfree_kernal(MINIKERNAL *in); extern void SHAVEinit_kernal(MINIKERNAL *in); extern void SHAVEupdate_kernal(MINIKERNAL *in,SHAVEPARMS *shavep); extern void MTmake_all_roots (MINIKERNAL *k); #include extern void MTdraw_lotsWFROOTPTREST( int slg, int ind, ROOTPT * outhair, GLOBS * gs ); extern void copy_rootpt(ROOTPT *out,ROOTPT *in); void init_geomROOTPT(ROOTPT *rp); extern void free_geomROOTPT(ROOTPT *rp); void find_closest_clump(ROOTPT *pt); typedef struct { int *list; int total; int threadID; int done; MINIKERNAL *m; } BUNCHLISTK; void allocate_roots(MINIKERNAL *k,int count) { int total; int t=0; int pq; VERT zero; int x; CURVEINFO cinfo; float sslider[SHAVE_NUM_PARAMS]; ROOTPT *outhair; total=count; k->total_roots=total; k->hair_roots=(ROOTPT *) malloc( total*sizeof(ROOTPT) ); for (x=0;xhair_roots[x]); zero.x=0.0f; zero.y=0.0f; zero.z=0.0f; t=0; // count the channels for( pq = 0; pq < SHAVE_NUM_PARAMS; pq++ ) { float sliderin = -1.0f; cinfo.hairID=0; sliderin = SHAVEapply_texture( &cinfo, zero, SHAVEID, pq, sliderin ); if (sliderin>=0.0f) t++; } // allocate the lists for (x=0;x0) { k->hair_roots[x].baked_tex= (float *) malloc(t*sizeof(float)); k->hair_roots[x].tex_link= (unsigned char *) malloc (t*sizeof(unsigned char *)); } k->hair_roots[x].total_tex=t; } // set up the links t=0; for( pq = 0; pq < SHAVE_NUM_PARAMS; pq++ ) { float sliderin = -1.0f; cinfo.hairID=0; sliderin = SHAVEapply_texture( &cinfo, zero, SHAVEID, pq, sliderin ); if (sliderin>=0.0f) for (x=0;xhair_roots[x].tex_link[t]=t; } if (sliderin>=0.0f) t++; } if (k->multiplier) { //k->multiplier_offsets=(VERT *) malloc( total*sizeof(VERT)*k->multiplier ); //k->multiplier_root_colors=(VERT *) malloc( total*sizeof(VERT)*k->multiplier ); //k->multiplier_tip_colors=(VERT *) malloc( total*sizeof(VERT)*k->multiplier ); // we're not going to prebake these afterall } //else { //k->multiplier_offsets=NULL; //k->multiplier_root_colors=NULL; //k->multiplier_tip_colors=NULL; } } void allocate_clumps(MINIKERNAL *k) { int x; k->total_clumps=Gclumps; if (k->total_clumps>k->total_roots) k->total_clumps=k->total_roots; k->clump_roots=(ROOTPT *) malloc(k->total_clumps*sizeof(ROOTPT) ); for (x=0;xtotal_clumps;x++) copy_rootpt(&k->clump_roots[x],&k->hair_roots[x]); } void free_guide(NEWGUIDES *k) { free(k->hv);k->hv=NULL; free(k->resthv);k->resthv=NULL; free(k->velocity);k->velocity=NULL; free(k->noisev);k->noisev=NULL; } void free_newguides(MINIKERNAL *k) { int x; int vts; int total; int segs; int mm; total=k->total_guides; segs=k->guide_segs; // segs will be 14 for now vts=segs; for (x=0;xguides[x]); } free(k->guides);k->guides=NULL; total=k->total_roots; segs=segs; // segs will be 14 for now vts=segs; mm=k->multiplier; if (mm<1) mm=1; { for (x=0;xreturn_hair[x]); } } free(k->return_hair);k->return_hair=NULL; k->total_guides=0; k->guide_segs=0; k->segs=0; //k->dirty=0; } void free_returnhairs(MINIKERNAL *k) { int x; int vts; int total; int segs; total=k->total_roots; segs=k->guide_segs; // segs will be 14 for now vts=segs; { for (x=0;xreturn_hair[x]); } } free(k->return_hair);k->return_hair=NULL; } void allocate_guide(NEWGUIDES *k,int vts) { VERT zero; int x; zero.x=0.0f; zero.y=0.0f; zero.z=0.0f; k->hv=(VERT *) malloc (sizeof(VERT)*vts); k->resthv=(VERT *) malloc (sizeof(VERT)*vts); k->velocity=(VERT *) malloc (sizeof(VERT)*vts); k->noisev=(VERT *) malloc (sizeof(VERT)*vts); for (x=0;xhv[x]=zero; k->resthv[x]=zero; k->velocity[x]=zero; k->noisev[x]=zero; } k->normal.x=0.0f; k->normal.y=0.0f; k->normal.z=0.0f; k->rest_normal.x=0.0f; k->rest_normal.y=0.0f; k->rest_normal.z=0.0f; k->rest_handle.x=0.0f; k->rest_handle.y=0.0f; k->rest_handle.z=0.0f; k->handle.x=0.0f; k->handle.y=0.0f; k->handle.z=0.0f; k->uu=0.0f; k->vv=0.0f; k->smoothing_group=0; } void allocate_newguides(MINIKERNAL *k) { int x; int vts; int total; int segs; int mm; mm=k->multiplier; if (mm<1) mm=1; total=k->total_guides; segs=k->guide_segs; // segs will be 14 for now vts=segs; k->dirty=0; k->guides= (NEWGUIDES *) malloc (total*sizeof(NEWGUIDES)); for (x=0;xguides[x],k->guide_segs); k->return_hair= (NEWGUIDES *) malloc (k->total_roots*sizeof(NEWGUIDES)*mm); for (x=0;xtotal_roots*mm;x++) allocate_guide(&k->return_hair[x],k->guide_segs); } void allocate_return_hair(MINIKERNAL *k) { int x; int vts; int total; int segs; int mm; mm=k->multiplier; if (mm==0) mm=1; total=k->total_roots*mm; segs=k->guide_segs; // segs will be 14 for now vts=segs; k->dirty=0; k->return_hair= (NEWGUIDES *) malloc (total*sizeof(NEWGUIDES)*mm); for (x=0;xtotal_roots*mm;x++) allocate_guide(&k->return_hair[x],k->guide_segs); } void MTresample_guides_kernal ( MINIKERNAL *m); void resize_base_hair_to_newguide( BASEHAIR * h, NEWGUIDES * ft, int segs ); extern void SHAVEupdate_kernal(MINIKERNAL *k,SHAVEPARMS *shavep) { int x; int vts; int total; int segs; BASEHAIR *get_guide; //k->total_clumps=Gclumps; //if (Gclumps>k->total_roots) k->total_clumps=k->total_roots; //if (k->total_clumps>k->total_roots) k->total_clumps=k->total_roots; //for (x=0;xtotal_clumps;x++) // copy_rootpt(&k->clump_roots[x],&Gindex[x]); // copy clumps total=k->total_guides; segs=k->guide_segs; // segs will be 14 for now vts=segs; // copy from cpu globals MTresample_guides_kernal ( k); for (x=0;xinterpolation_type!=MESH_GROWTH) get_guide=&Shair[x]; else get_guide=&hair[x]; if (k->interpolation_type==SPLINE_GROWTH) { get_guide->restlength=VdistanceK(get_guide->resthv[0],get_guide->resthv[1]); } //resize_base_hair_to_newguide(get_guide,&k->guides[x],k->guide_segs); k->guides[x].handle=get_guide->handle; k->guides[x].rest_handle=get_guide->resthandle; k->guides[x].normal=get_guide->norm; k->guides[x].uu=get_guide->uu; k->guides[x].vv=get_guide->vv; k->guides[x].smoothing_group=get_guide->splitgroup; k->guides[x].splitmerge=get_guide->splitmerge; } for (x=0;xslider_val[x]= shavep->slider_val[x][Gslg]; // slider settings k->instancing_status=shavep->instancing_status; k->geom_shadow=shavep->geom_shadow; k->tipfade=shavep->tipfade; k->multrot=shavep->multrot; // 4.0 - this is for twist on mult hairs k->spec_tint=shavep->spec_tint; // 4.0 - this is for rendering k->multrot_phase=shavep->multrot_phase; // 4.0 k->multrot_offset=shavep->multrot_offset; // 4.0 k->squirrel=shavep->squirrel; // 5.5 k->flyaway_percent=shavep->flyaway_percent; // 6.0 k->rand_seed_offset=shavep->rand_seed_offset; k->spec_tint2=shavep->spec_tint2; // 6.0.39 - this is for rendering } extern int SHAVEis_it_loaded(void) { int ret=0; if ((totalverts>0)||(Dtotalverts>0)||(total_splines>0)) ret=1; if (ret==0) fprintf (stdout,"engine is empty !\n");fflush(stdout); return(ret); } extern void SHAVEallocate_kernal(MINIKERNAL *in,SHAVEPARMS *shavep, int count, int segs) { int x,y,z; SHAVEmutex_lock(&Gtile_render_mutex); SHAVEfree_kernal(in); for (x=0;x<20;x++) for (y=0;y<20;y++) for (z=0;z<20;z++) in->noise[x][y][z]=noise[x][y][z]; mkbounds(); in->RESTBOUND=restBOUNDLENGTH; if (segs>15) segs=15; //in->hairlist=(int *) malloc(hairlist_size *sizeof(int)); //memcpy (in->hairlist,hairlist,sizeof(int)*hairlist_size); //in->hairlist_size=hairlist_size; in->total_roots=count; in->segs=segs; in->guide_segs=segs; in->total_guides=shavep->total_guides; //printf ("doh - totalguides = %d\n",in->total_guides); //in->guide_segs=15; // hard coded for now //if (in->guide_segs > in->segs) in->guide_segs=in->segs; // if guide segs are > segs, we're going to want to resize guides for efficiency to segs #define DREADCOUNT 25 #define DREADTIP 27 #define DREADROOT 26 #define OFFSET 45 #define ASPECT 46 for (x=0;xslider_val[x][Gslg]=shavep->slider_val[x][Gslg]; in->clump_roots=NULL; in->hair_roots=NULL; in->multiplier=(int)shavep->slider_val[DREADCOUNT][Gslg]; in->multrot_offset=shavep->slider_val[OFFSET][Gslg]; in->multrot=shavep->multrot; // no texture in->rand_seed_offset=shavep->rand_seed_offset; in->tipfade=shavep->tipfade; if (shavep->dontinterpolate) in->enable_interpolation=0; else in->enable_interpolation=1; if (Gslg==0) in->interpolation_type=MESH_GROWTH; if (Gslg==4) in->interpolation_type=SPLINE_GROWTH; //if (in->total_guides==0) in->interpolation_type=NONE; in->enable_interpolation=1; if (Gdontinterp) in->enable_interpolation=0; in->total_clumps=shavep->clumps; init_clumping (); allocate_roots(in,count); MTmake_all_roots (in); //allocate_clumps(in); //allocate_multroots(in); in->total_clumps=Gclumps; allocate_newguides(in); SHAVEupdate_kernal(in,shavep); SHAVEmutex_unlock(&Gtile_render_mutex); } void SHAVEfree_kernal(MINIKERNAL *in) { int x; in->interpolation_type=NONE; in->enable_interpolation=1; if (in->clump_roots) for (x=0;xtotal_clumps;x++) free_geomROOTPT(&in->clump_roots[x]); if (in->hair_roots) for (x=0;xtotal_roots;x++) free_geomROOTPT(&in->hair_roots[x]); if (in->hair_roots) free(in->hair_roots); in->hair_roots=NULL; if (in->clump_roots) free(in->clump_roots); in->clump_roots=NULL; //if (in->multiplier) free(in->multiplier_offsets);in->multiplier_offsets=NULL; //if (in->multiplier) free(in->multiplier_root_colors);in->multiplier_root_colors=NULL; //if (in->multiplier) free(in->multiplier_tip_colors);in->multiplier_tip_colors=NULL; if (in->guides) free_newguides(in); if (in->guides) free(in->guides); in->guides=NULL; if (in->return_hair) free_returnhairs(in); if (in->return_hair) free(in->return_hair); in->return_hair=NULL; if (in->hairlist) free(in->hairlist); in->hairlist=NULL; in->multiplier=0; in->total_clumps=0; in->total_roots=0; //SHAVEinit_kernal(in); //in->last_total_guides=0; } void SHAVEinit_kernal(MINIKERNAL *in) { int x; in->hairlist=NULL; in->interpolation_type=NONE; in->clump_roots=NULL; in->hair_roots=NULL; in->guides=NULL; in->return_hair=NULL; fprintf (stdout,"init kernal\n");fflush(stdout); //if (in->multiplier) free(in->multiplier_offsets);in->multiplier_offsets=NULL; //if (in->multiplier) free(in->multiplier_root_colors);in->multiplier_root_colors=NULL; //if (in->multiplier) free(in->multiplier_tip_colors);in->multiplier_tip_colors=NULL; in->multiplier=0; in->total_clumps=0; in->total_roots=0; //free_newguides(in); //free_returnhairs(in); //in->last_total_guides=0; } void free_geomROOTPT(ROOTPT *rp) { if (rp!=NULL) if (rp->total_tex>0) { if (rp->tex_link) free(rp->tex_link);rp->tex_link=NULL; if (rp->baked_tex) free(rp->baked_tex);rp->baked_tex=NULL; // if (rp) free (rp); rp->total_tex=0; } } void init_geomROOTPT(ROOTPT *rp) { rp->closest_clump = -1; rp->distance=0.0f; rp->tex_link=NULL; rp->total_tex=0; rp->baked_tex=NULL; } void init_geomROOTPTS(BUNCHROOT *br) { br->list=NULL; br->list_total=0; br->slg=Gslg; br->root=NULL; br->threadID=0; // init_geomROOTPT(br->root); //br->killme=0; } void alloc_geomROOTPTS(BUNCHROOT *br) { int x; CURVEINFO ci; int total_tex=0; if (br->list_total>0) { br->list=(int *) malloc(br->list_total*sizeof(int)); br->slg=Gslg; br->root=(ROOTPT *) malloc(br->list_total*sizeof(ROOTPT)); for( x = 0; x < SHAVE_NUM_PARAMS; x++ ) { VERT zero; float rt= -1.0f; ci.hairID=0; ci.groupID=Gslg; ci.depthpass=0; zero.z=0.0f;zero.y=0.0f;zero.z=0.0f; rt=SHAVEapply_texture(&ci,zero,SHAVEID,x, -1.0f); if (rt>=0.0f) total_tex++; } //total_tex=SHAVE_NUM_PARAMS; // I think this is causing a leak so lets see if it's for (x=0;xlist_total;x++) { br->root[x].total_tex=total_tex; if (total_tex!=0) { br->root[x].baked_tex=(float *) malloc (total_tex*sizeof(float)); br->root[x].tex_link=(unsigned char *) malloc (total_tex*sizeof(unsigned char)); } else {br->root[x].baked_tex=NULL;br->root[x].tex_link=NULL;} } br->threadID=0; } } void free_geomROOTPTS(BUNCHROOT *br) { int x; for (x=0;xlist_total;x++) free_geomROOTPT(&br->root[x]); if (br->list) free(br->list); br->list_total=0; } void MTgen_resthair_ROOTPT( ROOTPT *ret,int id, int slg, CURVEINFO * cinfo, GLOBS * gs ) { float a = 0.0f, b = 0.0f, c = 0.0f; float s = 0.0f, t = 0.0f; int tva = 0, tvb = 0, tvc = 0; int x = 0; int qq = 0; int pid = 0; int breakit = 1; /* map (s,t) to a point in that sub-triangle */ int va = 0, vb = 0, vc = 0; float uu = 1.0f, vvv = 1.0f; init_geomROOTPT( ret ); if( id >= total_slgfaces[slg] - 1 ) id = total_slgfaces[slg] - 1; pid = id; if( slg != 4 ) { va = facelist[face_start[id]]; vb = facelist[face_start[id] + 1]; vc = facelist[face_start[id] + 2]; ret->pntid1=va; ret->pntid2=vb; ret->pntid3=vc; } if( slg == 4 ) { int id1; id1 = id + 1; if( id1 > total_splines - 1 ) id1 = total_splines - 1; ret->pntid1=id; ret->pntid2=id1; ret->pntid3= -1; } if( slg ==0 ) { if( ( hair[va].splitgroup == hair[vb].splitgroup ) && ( hair[vb].splitgroup == hair[vc].splitgroup ) ) breakit = 0; if( hair[va].splitmerge + hair[vb].splitmerge + hair[vc].splitmerge > 0 ) breakit = 0; if( breakit == 0 ) { int qq; MTmix100(gs); uu = ( float ) MTdrand98( gs ); MTmix100(gs); vvv = ( float ) MTdrand98( gs ); s = uu; t = vvv; if( s + t > 1 ) { s = 1 - s; t = 1 - t; } vvv = t; a = s; b = t; c = ( 1 - s - t ); if( Gdontinterp == 1 ) { a = .333333333f; b = .333333333f; c = .333333333f; } ret->bary.x=a; ret->bary.y=b; ret->bary.z=c; for( x = 0; x < 1; x++ ) { VERT *hva, *hvb, *hvc; float fva, fvb, fvc; hva = &hair[va].resthv[x]; hvb = &hair[vb].resthv[x]; hvc = &hair[vc].resthv[x]; ret->resthv.x = a * hva->x + b * hvb->x + c * hvc->x; ret->resthv.y = a * hva->y + b * hvb->y + c * hvc->y; ret->resthv.z = a * hva->z + b * hvb->z + c * hvc->z; fva = hair[va].restlength; fvb = hair[vb].restlength; fvc = hair[vc].restlength; ret->restlength = a * fva + b * fvb + c * fvc; // assert(_CrtCheckMemory()); } } } if( slg == 0 ) if( breakit == 1 ) { // BASEHAIR tmpa,tmpb,tmpc; VERT basevert; int qq; float flip; MTmix100(gs); uu = ( float ) MTdrand98( gs ); MTmix100(gs); vvv = ( float ) MTdrand98( gs ); //*drand98 s = uu; t = vvv; if( s + t > 1 ) { s = 1 - s; t = 1 - t; } vvv = t; a = s; b = t; c = ( 1 - s - t ); if( Gdontinterp == 1 ) { a = .333333333f; b = .333333333f; c = .333333333f; } ret->bary.x=a; ret->bary.y=b; ret->bary.z=c; { VERT *hva, *hvb, *hvc; float fva, fvb, fvc; hva = &hair[va].resthv[0]; hvb = &hair[vb].resthv[0]; hvc = &hair[vc].resthv[0]; basevert.x = hva->x * a + hvb->x * b + hvc->x * c; basevert.y = hva->y * a + hvb->y * b + hvc->y * c; basevert.z = hva->z * a + hvb->z * b + hvc->z * c; ret->resthv=basevert; fva = hair[va].restlength; fvb = hair[vb].restlength; fvc = hair[vc].restlength; ret->restlength = a * fva + b * fvb + c * fvc; } flip = ( float ) MTdrand98( gs ); ret->flip=flip; } // slg!=4 // assert(_CrtCheckMemory()); if( slg == 4 ) { VERT *hva, *hvb, *hvc; float fva, fvb; int qq; int pid2; pid=id; pid2 = pid + 1; if( id > total_splines - 1 ) id = total_splines - 1; if( pid2 > total_splines - 1 ) pid2 = total_splines - 1; MTmix100(gs); uu = ( float ) MTdrand98( gs ); if( Gdontinterp == 1 ) uu = 0.0f; ret->resthv.x=Sresthair[pid].resthv[0].x*(1.0f-uu)+Sresthair[pid2].resthv[0].x*uu; ret->resthv.y=Sresthair[pid].resthv[0].y*(1.0f-uu)+Sresthair[pid2].resthv[0].y*uu; ret->resthv.z=Sresthair[pid].resthv[0].z*(1.0f-uu)+Sresthair[pid2].resthv[0].z*uu; ret->bary.x=1.0f - uu; ret->bary.y= uu; ret->bary.z= -1; fva = Sresthair[va].restlength; fvb = Sresthair[vb].restlength; ret->restlength = a * fva + b * fvb ; ret->killme=0; // assert(_CrtCheckMemory()); } } void threadedCall_MKROOTS (unsigned current_thread, void* qqq) { int x; BUNCHLISTK *bb; bb=(BUNCHLISTK *)(qqq); //assert(_CrtCheckMemory()); if (bb->total>0) MTmake_a_bunchROOT( bb->total, bb->list, bb->m, bb->threadID ); //assert(_CrtCheckMemory()); x=0; bb->done=1; } void copy_rootpt(ROOTPT *out,ROOTPT *in) { out->bary=in->bary; out->closest_clump=in->closest_clump; out->pntid1=in->pntid1; out->pntid2=in->pntid2; out->pntid3=in->pntid3; out->flip=in->flip; out->id=in->id; out->killme=in->killme; out->total_tex=in->total_tex; out->resthv=in->resthv; out->restlength=in->restlength; //out->baked_tex=(float *) malloc(in->total_tex*sizeof(float)); //out->tex_link=(unsigned char *) malloc(in->total_tex*sizeof(unsigned char)); //if (in->killme==0) if (in->total_tex>0) { memcpy(out->baked_tex,in->baked_tex,sizeof (float)*in->total_tex); memcpy(out->tex_link,in->tex_link,sizeof (unsigned char)*in->total_tex); } } void MTbunch_of_roots (int list_total, int *inlist,int slg, MINIKERNAL *br); void MTmake_all_roots (MINIKERNAL *k) { int x; int *list=NULL; int tt=0; int total; //if (Gslg==0) //total=LOCAL_CNT[0]; //if (Gslg==4) //total=LOCAL_CNT[4]; total=k->total_roots; //if (k->hairlist) free (k->hairlist); // we're ignoring the input list because we're making them all //k->hairlist= (int *) malloc (total*sizeof(int)); list=(int *) malloc (total*sizeof(int)); for (x=0;x0) { int t=0; int pp; //printf ("bb->pass = %d\n",pass);fflush(stdout); mult=(int)sliders[25][slg].value; if (mult<1) mult=1; th=SHAVEnum_processors(); if (list_total0) for (xxx=0;xxxinc) ltotal=inc; //assert(_CrtCheckMemory()); bb->done=0; bb->total=ltotal; //assert(_CrtCheckMemory()); //assert(_CrtCheckMemory()); bb->list= (int *) malloc((list_total+1)*sizeof(int)); done=0; while (done==0) { bb->list[xx]=inlist[count]; count++; xx++; if ((xx==inc)) done=1; if (count==list_total) done=1; } bb->total=xx; bb->m=k; #ifdef _WIN32 //assert(_CrtCheckMemory()); #endif bb->threadID=xxx; if (th>=2) { if (bb->total>0) SHAVEstart_thread (threadGroup,threadedCall_MKROOTS,(void*) bb); } else threadedCall_MKROOTS(0,(void*)bb); #ifdef _WIN32 //assert(_CrtCheckMemory()); #endif } //fixed here if ( (th>=2)) SHAVEend_thread_group(threadGroup); done=0; if ( (th>=2)) while (done==0) { int x; float cnt=0; for (x=0;xGslg=slg; if( total_slgfaces[Gslg] > 0 ) { int q; int cnnt; // WFTYPE wf; int dok = 1; //assert(_CrtCheckMemory()); // init_geomROOTPT( &wf ); //assert(_CrtCheckMemory()); if( total_slgfaces[Gslg] > 0 ) if( LOCAL_CNT[Gslg] > 0 ) if( LOCAL_PASSES[Gslg] > 0 ) { float d1, d2; BASEHAIR hrest; BASEHAIR h; hrest.killme = 0; for (x=0;xhair_roots[hid], >hreads[threadID] ); //assert(_CrtCheckMemory()); if (Gclumps>0) find_closest_clump(&m->hair_roots[hid]); //assert(_CrtCheckMemory()); // free_geomROOTPT(&wf); } } //assert(_CrtCheckMemory()); if (list) free(list);list=NULL; } } void MTdraw_lotsWFROOTPTREST( int slg, int ind, ROOTPT * outhair, GLOBS * gs ) { // BASEHAIR rtt[20]; CURVEINFO ci; CURVEINFO *cinfo; int nokink = 1; int pd; float jfloat; // BASEHAIR hh[20]; float ascalh, ascalr; VERT t1[15], t2[15]; int qv; VERT xv, yv, zv, b; int pid = 0; int killit = 0; BASEHAIR h; float d1 = 1.0, d2 = 1.0f; BASEHAIR hrest; int x; int cc; int cc2; int cloneON = 0; static int chk = 1; static int lp; int index; int indx; //int samp; cinfo=&ci; //assert(_CrtCheckMemory()); cinfo->shadowHair = 1; if( ind > LOCAL_SHADCNT[slg] ) cinfo->shadowHair = 0; init_a_hair( &hrest ); init_a_hair( &h ); cloneON=0; h.killme = 0; cinfo->killme = 0; h.killme = 0; hrest.killme = 0; cinfo->killme = 0; killit = 0; hrest.killme = 0; cinfo->killme = 0; cinfo->diff = 0.0f; cinfo->kspec = 0.0f; cinfo->norm.x = 0.0f; cinfo->norm.y = 1.0f; cinfo->norm.z = 0.0f; cinfo->shad = 0.0f; cinfo->spec = 0.0f; cinfo->tiprad = 0.0f; cinfo->baserad = 0.0f; // cinfo->hairID = gs->GhairID; cinfo->hairID = ind; cinfo->nodeID = GnodeID; // cinfo->depthpass = gs->passnumber; cinfo->ambient = 0.0f; cinfo->restlength = 0.0f; cinfo->cutlength = 0.0f; cinfo->mtl = slg; cinfo->u = 0; cinfo->v = 0; cinfo->u2 = 0; cinfo->v2 = 0; x = ind; gs->random_seed_offset=Grandom_seed_offset; cloneON=0; { // int cll; // cll=sliders[25][slg].value; // if (cll==0) cll=1; // indx= ind*cll+cll*LOCAL_CNT[slg]*LOCAL_PASSES[slg]; indx=ind; } hrest.hairnumber=x; chk=1; //assert(_CrtCheckMemory()); { MTJsrand(ind,gs); mixitup( ); { int pd; float rand1; float rand2; rand1 = ( float ) MTdrand98( gs ); rand2 = ( float ) MTdrand98( gs ); for( pd = 0; pd < ( int ) ( 37. * rand1 + 10. * 0. /*cc*/ * rand2 ); pd++ ) { float jjunk; jjunk = ( float ) MTdrand98( gs ); } } } { if( total_slgfaces[slg] > 0 ) if( LOCAL_CNT[slg] > 0 ) { if( slg == 4 ) pid = (int)( floor ) ( ( float ) MTdrand98( gs ) * ( ( double ) total_slgfaces[slg] - 1 ) - .000001f ); // pid=(floor)((float)MTdrand98(gs)*((double)total_slgfaces[slg]-1)-.000001f); if( slg != 4 ) { int rp = 0; rp = ( int ) ( ( float ) MTdrand98( gs ) * ( ( double ) total_slgfaces[slg] ) - .000001f ); if( rp > total_slgfaces[slg] - 1 ) rp = total_slgfaces[slg] - 1; pid = slgfaces[slg][rp]; } // if (slg!=4) if( total_slgfaces[slg] > 0 ) if( pid > total_slgfaces[slg] - 1 ) pid = total_slgfaces[slg] - 1; // pid = slgfaces[slg][pid]; chk = 1; if( killit == 0 ) if( total_slgfaces[slg] > 0 ) if( LOCAL_CNT[slg] > 0 ) if( slg != 4 ) { while( ( MTcheckface( pid, gs ) == 0 ) ) //||(pid==total_slgfaces[slg])) { int rp; rp = ( int ) ( ( float ) MTdrand98( gs ) * ( ( double ) total_slgfaces[slg] ) - .000001f ); if( rp > total_slgfaces[slg] - 1 ) rp = total_slgfaces[slg] - 1; pid = slgfaces[slg][rp]; } } } } //assert(_CrtCheckMemory()); if( total_slgfaces[slg] > 0 ) if( LOCAL_CNT[slg] > 0 ) { int lp; lp = LOCAL_PASSES[slg]; //lp-=1;if (lp<1) lp=1; mixitup( ); killit = 0; cinfo->killme = 0; MTJsrand(indx,gs); mixitup( ); MTgen_resthair_ROOTPT( outhair,pid, slg, cinfo, gs ); //assert(_CrtCheckMemory()); MTJsrand(indx,gs); //MTcolor_a_hairROOTPT(outhair,gs); outhair->id=x; { unsigned char t=0; int pq; float sslider[SHAVE_NUM_PARAMS]; // free(outhair->baked_tex); // free(outhair->tex_link); hrest.resthv[0]=outhair->resthv; hrest.hv[0]=outhair->resthv; hrest.resthv[0]=outhair->resthv; hrest.noisev[0]=outhair->resthv; hrest.killme=0; if (Gslg==0) { hrest.uu=hair[outhair->pntid1].uu*outhair->bary.x+hair[outhair->pntid2].uu*outhair->bary.y+hair[outhair->pntid3].uu*outhair->bary.z; hrest.vv=hair[outhair->pntid1].vv*outhair->bary.x+hair[outhair->pntid2].vv*outhair->bary.y+hair[outhair->pntid3].vv*outhair->bary.z; hrest.restlength=hair[outhair->pntid1].restlength*outhair->bary.x+hair[outhair->pntid2].restlength*outhair->bary.y+hair[outhair->pntid3].restlength*outhair->bary.z; } else { hrest.uu=Shair[outhair->pntid1].uu*outhair->bary.x+Shair[outhair->pntid2].uu*outhair->bary.y+Shair[outhair->pntid3].uu*outhair->bary.z; hrest.vv=Shair[outhair->pntid1].vv*outhair->bary.x+Shair[outhair->pntid2].vv*outhair->bary.y+Shair[outhair->pntid3].vv*outhair->bary.z; hrest.restlength=Shair[outhair->pntid1].restlength*outhair->bary.x+Shair[outhair->pntid2].restlength*outhair->bary.y; } hrest.Bid1=outhair->pntid1; hrest.Bid2=outhair->pntid3; hrest.Bid3=outhair->pntid3; cinfo->pntid[0]=outhair->pntid1; cinfo->pntid[1]=outhair->pntid2; cinfo->pntid[2]=outhair->pntid3; cinfo->wgt[0]=outhair->bary.x; cinfo->wgt[1]=outhair->bary.y; cinfo->wgt[2]=outhair->bary.z; outhair->restlength=hrest.restlength; #ifdef _WIN32 assert(_CrtCheckMemory()); #endif t=0; for( pq = 0; pq < outhair->total_tex; pq++ ) { float sliderin = -1.0f; VERT zero; zero.x=0.0f; zero.y=0.0f; zero.z=0.0f; cinfo->hairID=ind; //thread safe? sliderin = SHAVEapply_texture( cinfo, outhair->resthv, SHAVEID, outhair->tex_link[pq], sliderin ); if (sliderin>=0.0f) { outhair->baked_tex[outhair->tex_link[pq]]=sliderin; // outhair->tex_link[t]= (unsigned char ) pq; // t++; } } for (x=0;xtotal_tex; pq++ ) { sslider[outhair->tex_link[pq]]=outhair->baked_tex[outhair->tex_link[pq]]; } outhair->killme = 0; #ifdef _WIN32 //assert(_CrtCheckMemory()); #endif MTJsrand( ( unsigned long ) ( outhair->id * 11 ), gs ); { int xx; for( xx = 0; xx < 5; xx++ ) MTdrand98( gs ); } if (sslider[DENSITY] >= 0.0f) if( sslider[DENSITY] * sslider[DENSITY] < MTdrand98( gs ) ) outhair->killme = 1; } } }