// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 int firstuseVOX = 1; ////VOXEL boundvox; ////VOXHAIR *voxhair=NULL; //int totalvoxhair=0; #define VXLIMIT 65 #define VXLIMIT1 66 float VDot( VERT a, VERT b ); typedef struct { float din, dout; float u; int hairno; int segno; VERT norm; VERT velocity; VERT cin; char total; VERT color; float spec, gloss, diff, shad, opacity; int flag; int instid; } TRACEINFO; typedef struct { TRACEINFO ti[35]; } HVOXRET; //int haircount; //int PASSES; typedef struct { int hairno; unsigned char segno; } HSEG; typedef struct { float radbase; float radtip; float minrad; // unsigned char slg; VERT *hv; VERT *velocity; VERT colorroot; VERT colortip; VERT *color; float spec, gloss, diff, shad, opacity; int slg; // could also be a char unsigned char killme; int segs; VERT norm; // float cutlength; } VOXHAIR; void illuminate_strandVH( VOXHAIR * vh ); typedef struct { VERT bound1, bound2; HSEG *segs; int totalseg; unsigned char tag; } VOXEL; typedef struct st_SHAVEdata { LWItemID id; int instancing; float time; int frame; int lastframe; char objfile[800]; char hairfile[800]; char statfile[800]; char instancefile[800]; char geom[255]; int enable; int offset; int totalverts; int cv; float frame_rate; int haircount[5]; VERT *vdat; VOXHAIR *voxhair; ///=NULL; BASEHAIR *cached_hair; int cache_count; int totalhairs; LWItemID itemid; int pregen; int enabled; int world; float scale; int segs[5]; int twister; int dolly; float speed; // char baseName[255]; int digits; VOXEL allvox[( VXLIMIT1 ) * ( VXLIMIT1 ) * ( VXLIMIT1 )]; VOXEL boundvox; float boundvoxlength; int PASSES[5]; int clone[5]; float fuzz; int fire; int raycast; float restBOUNDLENGTH; SLIDER OVERhair[33]; SLIDER OVERbeard[33]; SLIDER OVEReyebrow[33]; SLIDER OVEReyelash[33]; } VXSHAVEdata; /* * ANSI C code from the article * "Intersecting a Ray with a Cylinder" * by Joseph M. Cychosz and Warren N. Waggenspack, Jr., * (3ksnn64@ecn.purdue.edu, mewagg@mewnw.dnet.lsu.edu) * in "Graphics Gems IV", Academic Press, 1994 */ ////#include "GraphicsGems.h" #include /* ---- intcyl - Intersect a ray with a cylinder. --------------------- */ /* */ /* */ /* Description: */ /* Intcyl determines the intersection of a ray with a */ /* cylinder. */ /* */ /* On entry: */ /* raybase = The base point of the intersecting ray. */ /* raycos = The direction cosines of the above ray. (unit) */ /* base = The base location of the cylinder. */ /* axis = The axis of symmetry for the cylinder. (unit) */ /* radius = The radius of the cylinder. */ /* */ /* On return: */ /* in = The entering distance of the intersection. */ /* out = The leaving distance of the intersection. */ /* */ /* Returns: True if the ray intersects the cylinder. */ /* */ /* Note: In and/or out may be negative indicating the */ /* cylinder is located behind the origin of the ray. */ /* */ /* -------------------------------------------------------------------- */ #ifdef _WIN32 #define HUGE 1.0e21 /* Huge value */ #endif int intcyl( VERT * raybase, /* Base of the intersection ray */ VERT * raycos, /* Direction cosines of the ray */ VERT * base, /* Base of the cylinder */ VERT * axis, /* Axis of the cylinder */ float radius, /* Radius of the cylinder */ float *in, /* Entering distance */ float *out /* Leaving distance */ ); float V3SquaredLength( VERT * a ) { return ( ( a->x * a->x ) + ( a->y * a->y ) + ( a->z * a->z ) ); } float V3Length( VERT * a ) { return ( sqrt( V3SquaredLength( a ) ) ); } /* return the dot product of vectors a and b */ float V3Dot( VERT * a, VERT * b ) { return ( ( a->x * b->x ) + ( a->y * b->y ) + ( a->z * b->z ) ); } /* return the cross product c = a cross b */ VERT * V3Cross( VERT * a, VERT * b, VERT * c ) { c->x = ( a->y * b->z ) - ( a->z * b->y ); c->y = ( a->z * b->x ) - ( a->x * b->z ); c->z = ( a->x * b->y ) - ( a->y * b->x ); return ( c ); } /* normalizes the input vector and returns it */ VERT * V3Normalize( VERT * v ) { float len = V3Length( v ); if( len != 0.0 ) { v->x /= len; v->y /= len; v->z /= len; } return ( v ); } //int intcyl (Point3cyl *,Vector3 *,Point3cyl *,Vector3 *,float,float *,float *); int isphere( VERT rayo, VERT ray, VERT sphc, float sphrad, TRACEINFO * ti ) { VERT oc; float v; int notinside = 1; // TRACEINFO ti; float t; oc.x = sphc.x - rayo.x; oc.y = sphc.y - rayo.y; oc.z = sphc.z - rayo.z; // float dy = sphc.y - rayo.y; // float dz = sphc.z - rayo.z; v = VDot( oc, ray ); // Do the following quick check to see if there is even a chance // that an intersection here might be closer than a previous one //if (v - radius ray.t) // return false; // Test if the ray actually intersects the sphere t = sphrad * sphrad + v * v - oc.x * oc.x - oc.y * oc.y - oc.z * oc.z; if( t < 0 ) { ti->flag = 0; return ( 0 ); } // return false; // Test if the intersection is in the positive // ray direction and it is the closest so far t = v - ( ( float ) sqrt( t ) ); // if ((t ray.t) || (t < 0)) if( ( t < 0 ) ) { ti->flag = 0; return ( 0 ); } // return false; ti->flag = 1; ti->din = t; ////ti->din=sqrt(oc.x*oc.x+oc.y*oc.y+oc.z*oc.z)-sphrad/2.0f; ti->dout = t + sphrad; // ray.object = this; // return true; if( sphrad * sphrad > oc.x * oc.x + oc.y * oc.y + oc.z * oc.z ) notinside = 0; if( notinside ) return ( 1 ); else return ( 0 ); } int intcyl( VERT * raybase, /* Base of the intersection ray */ VERT * raycos, /* Direction cosines of the ray */ VERT * base, /* Base of the cylinder */ VERT * axis, /* Axis of the cylinder */ float radius, /* Radius of the cylinder */ float *in, /* Entering distance */ float *out /* Leaving distance */ ) { int hit; /* True if ray intersects cyl */ VERT RC; /* Ray base to cylinder base */ float d; /* Shortest distance between */ /* the ray and the cylinder */ float t, s; /* Distances along the ray */ VERT n, D, O; float ln; const float pinf = ( float ) 100000000.0f; /* Positive infinity */ RC.x = raybase->x - base->x; RC.y = raybase->y - base->y; RC.z = raybase->z - base->z; axis->x = axis->x; axis->y = axis->y; axis->z = axis->z; V3Cross( raycos, axis, &n ); if( ( ln = V3Length( &n ) ) == 0. ) { /* ray parallel to cyl */ d = V3Dot( &RC, axis ); D.x = RC.x - d * axis->x; D.y = RC.y - d * axis->y; D.z = RC.z - d * axis->z; d = V3Length( &D ); *in = -pinf; *out = pinf; return ( d <= radius ); /* true if ray is in cyl */ } V3Normalize( &n ); d = fabs( V3Dot( &RC, &n ) ); /* shortest distance */ hit = ( d <= radius ); if( hit ) { /* if ray hits cylinder */ V3Cross( &RC, axis, &O ); t = -V3Dot( &O, &n ) / ln; V3Cross( &n, axis, &O ); V3Normalize( &O ); s = fabs( sqrt( radius * radius - d * d ) / V3Dot( raycos, &O ) ); *in = t - s; /* entering distance */ *out = t + s; /* exiting distance */ } return ( hit ); } int trace_pill( VERT rbase, VERT rdir, VERT cbase, VERT cdir, float crad, float clen, TRACEINFO * ti ) { //TRACEINFO ti; int hitit = 0; VERT actualp; VERT diff; float raybase[3], raycos[3], base[3], axis[3], radius, ind, outd; ind = 0; outd = 0; raybase[0] = rbase.x; raybase[1] = rbase.y; raybase[2] = rbase.z; raycos[0] = rdir.x; raycos[1] = rdir.y; raycos[2] = rdir.z; base[0] = cbase.x; base[1] = cbase.y; base[2] = cbase.z; axis[0] = cdir.x; axis[1] = cdir.y; axis[2] = cdir.z; radius = crad; ti->flag = 0; if( clen > 0 ) { //TRACEINFO st; // first test a sphere //{ // VERT rb; // float cln; // cln=(clen+crad*2.0); // rb.x=cbase.x;//+rdir.x*cln; // rb.y=cbase.y;//+rdir.y*cln; // rb.z=cbase.z;//+rdir.z*cln; //st= isphere(rbase, rdir,rb,cln); //} //if (st.flag==1) hitit = intcyl( &rbase, &rdir, &cbase, &cdir, radius, &ind, &outd ); ti->flag = ( char ) hitit; if( hitit ) { VERT a, b; //int clipobj (raybase,raycos,bot,top,objin,objout,surfin,surfout) //hitit*=clipobj(raybase,raycos,objin,&objout,surfin,&surfout); actualp.x = rbase.x + rdir.x * ( ind + outd ) / 2.0f; actualp.y = rbase.y + rdir.y * ( ind + outd ) / 2.0f; actualp.z = rbase.z + rdir.z * ( ind + outd ) / 2.0f; diff.x = actualp.x - cbase.x; diff.y = actualp.y - cbase.y; diff.z = actualp.z - cbase.z; a = cbase; b.x = cbase.x + cdir.x * clen; b.y = cbase.y + cdir.y * clen; b.z = cbase.z + cdir.z * clen; ti->flag = 0; { VERT aa, bb; aa.x = b.x - a.x; aa.y = b.y - a.y; aa.z = b.z - a.z; bb.x = actualp.x - a.x; bb.y = actualp.y - a.y; bb.z = actualp.z - a.z; aa = Vnorm( aa ); bb = Vnorm( bb ); if( VDot( aa, bb ) >= 0 ) { aa.x = a.x - b.x; aa.y = a.y - b.y; aa.z = a.z - b.z; bb.x = actualp.x - b.x; bb.y = actualp.y - b.y; bb.z = actualp.z - b.z; aa = Vnorm( aa ); bb = Vnorm( bb ); if( VDot( aa, bb ) >= 0 ) ti->flag = 1; } } if( ti->flag == 1 ) { ti->u = sqrt( diff.x * diff.x + diff.y * diff.y + diff.z * diff.z ); ti->u /= clen; if( ti->u > 1 ) ti->u = 1; } // if (ti->u<0) ti->flag=0; // if (ti->u>=1) ti->flag=0; } } ti->din = ind; ti->dout = outd; //ti->flag=(char) 1; // test to see if origin is inside cylender if( ti->flag == 1 ) { VERT dvv; float dd; dvv.x = rbase.x - actualp.x; dvv.y = rbase.y - actualp.y; dvv.z = rbase.z - actualp.z; if( ( radius * radius * 2 ) > dvv.x * dvv.x + dvv.y * dvv.y + dvv.z * dvv.z ) // ok it's inside don't hit it ti->flag = 0; } if( ti->flag == 0 ) { VERT sphc; sphc.x = cbase.x + cdir.x * clen; sphc.y = cbase.y + cdir.y * clen; sphc.z = cbase.z + cdir.z * clen; isphere( rbase, rdir, sphc, crad, ti ); ti->u = 1.0f; } return ( 1 ); } /* Fast Ray-Box Intersection by Andrew Woo from "Graphics Gems", Academic Press, 1990 */ //#include "GraphicsGems.h" #define RBNUMDIM 3 #define RBRIGHT 0 #define RBLEFT 1 #define RBMIDDLE 2 char HitBoundingBox( float minB[RBNUMDIM], float maxB[RBNUMDIM], /*box */ float origin[RBNUMDIM], float dir[RBNUMDIM], /*ray */ float coord[RBNUMDIM] ) /* hit point */ { char inside = 1; char quadrant[RBNUMDIM]; register int i; int whichPlane; float maxT[RBNUMDIM]; float candidatePlane[RBNUMDIM]; /* Find candidate planes; this loop can be avoided if rays cast all from the eye(assume perpsective view) */ for( i = 0; i < RBNUMDIM; i++ ) if( origin[i] < minB[i] ) { quadrant[i] = RBLEFT; candidatePlane[i] = minB[i]; inside = 0; } else if( origin[i] > maxB[i] ) { quadrant[i] = RBRIGHT; candidatePlane[i] = maxB[i]; inside = 0; } else { quadrant[i] = RBMIDDLE; } /* Ray origin inside bounding box */ if( inside ) { coord = origin; return ( 1 ); } /* Calculate T distances to candidate planes */ for( i = 0; i < RBNUMDIM; i++ ) if( quadrant[i] != RBMIDDLE && dir[i] != 0. ) maxT[i] = ( candidatePlane[i] - origin[i] ) / dir[i]; else maxT[i] = -1.0f; /* Get largest of the maxT's for final choice of intersection */ whichPlane = 0; for( i = 1; i < RBNUMDIM; i++ ) if( maxT[whichPlane] < maxT[i] ) whichPlane = i; /* Check final candidate actually inside box */ if( maxT[whichPlane] < 0. ) return ( 0 ); for( i = 0; i < RBNUMDIM; i++ ) if( whichPlane != i ) { coord[i] = origin[i] + maxT[whichPlane] * dir[i]; if( coord[i] < minB[i] || coord[i] > maxB[i] ) return ( 0 ); } else { coord[i] = candidatePlane[i]; } return ( 1 ); /* ray hits box */ } TRACEINFO raybox( VERT rbase, VERT rdir, VERT b1, VERT b2 ) { char ret; TRACEINFO ti; float maxB[3], minB[3], origin[3], dir[3], coord[3]; minB[0] = b1.x; minB[1] = b1.y; minB[2] = b1.z; maxB[0] = b2.x; maxB[1] = b2.y; maxB[2] = b2.z; origin[0] = rbase.x; origin[1] = rbase.y; origin[2] = rbase.z; dir[0] = rdir.x; dir[1] = rdir.y; dir[2] = rdir.z; ret = HitBoundingBox( minB, maxB, origin, dir, coord ); ti.cin.x = coord[0]; ti.cin.y = coord[1]; ti.cin.z = coord[2]; ti.flag = ( char ) ret; return ( ti ); } static void VXinit( void ); static void VXcreate( void ); // this is a pointer to the hair number and the seg number // this is what gets stuffed into a voxel; //FILE *fdg=NULL; ////VOXEL allvox[VXLIMIT][VXLIMIT][VXLIMIT]; #include //#include "voxels.h" static VXSHAVEdata *VLPD[255]; // int totalinst=0; static void VXinit_bound( VXSHAVEdata * dat, int wipecolor ); //#include "ray_cyl.c" #include "subdiv.c" static void HVillum( VOXHAIR * vh, int hn, TRACEINFO * hr ); typedef struct { float diffamb; float spec; float kspec; VERT color; } SHADEME; typedef struct { int x, y, z; } TRIPLEINT; static int VoxLine( int x, int y, int z, int dx, int dy, int dz, TRIPLEINT * hitvox ) //int x, y, z, dx, dy, dz; { int n, sx, sy, sz, exy, exz, ezy, ax, ay, az, bx, by, bz; int total = 0; int done = 0; sx = SGN( dx ); sy = SGN( dy ); sz = SGN( dz ); ax = abs( dx ); ay = abs( dy ); az = abs( dz ); bx = 2 * ax; by = 2 * ay; bz = 2 * az; exy = ay - ax; exz = az - ax; ezy = ay - az; n = ax + ay + az; while( ( n-- ) && ( done == 0 ) ) { /// VisitVoxel ( x, y, z ); if( ( x >= 0 ) && ( y >= 0 ) && ( z >= 0 ) && ( x < VXLIMIT ) && ( y < VXLIMIT ) && ( z < VXLIMIT ) ) { hitvox[total].x = x; hitvox[total].y = y; hitvox[total].z = z; total++; } else done = 1; if( exy < 0 ) { if( exz < 0 ) { x += sx; exy += by; exz += bz; } else { z += sz; exz -= bx; ezy += by; } } else { if( ezy < 0 ) { z += sz; exz -= bx; ezy += by; } else { y += sy; exy -= bx; ezy -= bz; } } } return ( total ); } float specshade_vertex( VERT vv, VERT norm, VERT lightv, float speccomp, float specexcomp ) { float spec; int a, b; VERT H; VERT eye; float shd; eye.x = LWcam.wpos.x - vv.x; eye.y = LWcam.wpos.y - vv.y; eye.z = LWcam.wpos.z - vv.z; eye = Vnorm( eye ); { VERT T, L, V; float shd2 = 0.0f; shd = 0.0f; T = norm; L = lightv; V = eye; { float tsq; tsq = VDot( L, T ); tsq *= tsq; tsq=1.0f-tsq; if (tsq<0.0f) tsq=0.0f; shd2 = sqrt( tsq ); } if( shd2 > 0 ) shd += shd2; { float spec2; { float tsq; tsq = VDot( V, T ); spec2 = shd2 * sqrt( fabs(1.0 - tsq * tsq) ) - VDot( L, T ) * tsq; } if( spec2 < 0 ) spec2 = 0; spec = pow( spec2, 1.0 / ( 3.0 * ( .101 - specexcomp ) ) ); } } return ( spec ); } static float diffshade_vertex( VERT vv, VERT norm, VERT lightv, float diffcomp ) { float diff, spec; int a, b; VERT H; diff = VDot( lightv, norm ); //diff= -diff; // if( diff < 0.0 ) // diff=0; diff *= diff; diff *= diffcomp; { float idiffcomp; idiffcomp=1.0f-diffcomp; if (idiffcomp<0.0f) idiffcomp=0.0f; diff += ( idiffcomp ); } return ( diff ); } static VERT make_hair_norm( int hn, int seg, int lightindex, VXSHAVEdata * dat ) { VERT vv; float diffcomp; float speccomp; float specexcomp; float diff, spec; VERT norm, lv, tmp; int a, b; VERT H; VERT eye; float tsq; vv = dat->voxhair[hn].hv[seg]; a = seg; b = seg + 1; if( a > dat->voxhair[hn].segs - 2 ) a = dat->voxhair[hn].segs - 2; if( b > dat->voxhair[hn].segs - 1 ) b = dat->voxhair[hn].segs - 1; norm.x = dat->voxhair[hn].hv[b].x - dat->voxhair[hn].hv[a].x; norm.y = dat->voxhair[hn].hv[b].y - dat->voxhair[hn].hv[a].y; norm.z = dat->voxhair[hn].hv[b].z - dat->voxhair[hn].hv[a].z; norm = Vnorm( norm ); return ( norm ); } static VERT make_hair_rad_norm( int hn, int seg, VERT ldir, VXSHAVEdata * dat ) { VERT vv; float diffcomp; float speccomp; float specexcomp; float diff, spec; VERT norm, lv, tmp; int a, b; VERT H; vv = dat->voxhair[hn].hv[seg]; a = seg; b = seg + 1; if( a > dat->voxhair[hn].segs - 2 ) a = dat->voxhair[hn].segs - 2; if( b > dat->voxhair[hn].segs - 1 ) b = dat->voxhair[hn].segs - 1; norm.x = dat->voxhair[hn].hv[b].x - dat->voxhair[hn].hv[a].x; norm.y = dat->voxhair[hn].hv[b].y - dat->voxhair[hn].hv[a].y; norm.z = dat->voxhair[hn].hv[b].z - dat->voxhair[hn].hv[a].z; norm = Vnorm( norm ); lv = ldir; tmp = Vcross( norm, lv ); norm = Vcross( tmp, norm ); return ( norm ); } VXSHAVEdata *Gvoxdata[255]; static void Shave_Trace( VERT rbase, VERT rdir, VXSHAVEdata * dat, double fC, int shademe, TRACEINFO * tracestack ); int VXtrace( float nearClip, float farClip, VERT rbase, VERT rdir, int shademe, VOXSAMP * vsamp ); void VXtest( int xres, int yres, unsigned char *image ) { int x, y; VXinit( ); printf( "VXcreate()\n" ); VXcreate( ); printf( "done VXcreate()\n" ); for( x = 0; x < xres; x++ ) for( y = 0; y < yres; y++ ) { VERT2 wpos; VERT pos; VERT ray; VOXSAMP vs; wpos.x = ( float ) x; wpos.y = ( float ) y; wpos.z = .1f; wpos = cam2world( &LWcam, wpos ); wpos.z = ( ( ( float ) x / ( float ) xres ) - 0.5f ) * 1.0f; wpos.y = ( ( ( float ) y / ( float ) yres ) - 0.5f ) * 1.0 + .5f; wpos.x = -4.0f; // ray.x=wpos.x-LWcam.wpos.x; /// ray.y=wpos.y-LWcam.wpos.y; /// ray.z=wpos.z-LWcam.wpos.z; /// ray.x*= -1.0f; /// ray.y*= -1.0f; /// ray.z*= -1.0f; ray.z = 0; ray.y = 0; ray.x = 1.0f; pos.x = wpos.x; pos.y = wpos.y; pos.z = wpos.z; // ray.z*= -1; ray = Vnorm( ray ); VXtrace( 0.0f, 1000000.0f, pos, ray, 1, &vs ); if( vs.distance > 0 ) printf( "x %d y %d dist = %f %f %f %f \n ", x, y, vs.distance, vs.velocity.x, vs.velocity.y, vs.velocity.z ); // if (vs.distance>0) { int add; add = x + y * xres; add *= 4; image[add] = ( unsigned char ) ( vs.color.x * 255.0 ); image[add + 1] = ( unsigned char ) ( vs.color.y * 255.0 ); image[add + 2] = ( unsigned char ) ( vs.color.z * 255.0 ); image[add + 3] = ( unsigned char ) ( vs.opacity * 255.0 ); } } } void SHAVEtrace_init( void ) { firstuseVOX = 1; //. printf ("trace init\n"); printf( "Shave trace as been initialiazed.\n" ); fflush( stdout ); VXinit( ); VXcreate( ); } int SHAVEtrace( float nearClip, float farClip, VERT rbase, VERT rdir, int shademe, VOXSAMP * vsamp ) { // return ( 0); return ( VXtrace( nearClip, farClip, rbase, rdir, shademe, vsamp ) ); } static void shade_a_curve( CURVEINFO * hp, WFTYPE * wf ); void illuminate_strandVH( VOXHAIR * vh ) { int x; CURVEINFO ci; WFTYPE wf; wf.totalverts = vh->segs; wf.totalfaces = 1; wf.totalfverts = vh->segs; alloc_geomWF( &wf ); wf.face_start[0] = 0; wf.face_end[0] = vh->segs; wf.totalverts = vh->segs; wf.totalfaces = 1; wf.totalfverts = vh->segs; for( x = 0; x < vh->segs; x++ ) { float bb, bb1; bb = ( float ) x / ( float ) vh->segs; bb1 = 1.0f - bb; if (bb1<0.0f) bb1=0.0f; if (bb>1.0f) bb=1.0f; wf.facelist[x] = x; wf.color[x].x = ( vh->colorroot.x * bb1 + vh->colortip.x * bb ) / 255.0f; wf.color[x].y = ( vh->colorroot.y * bb1 + vh->colortip.y * bb ) / 255.0f; wf.color[x].z = ( vh->colorroot.z * bb1 + vh->colortip.z * bb ) / 255.0f; wf.v[x] = vh->hv[x]; wf.velocity[x].x = 0.0f; wf.velocity[x].y = 0.0f; wf.velocity[x].z = 0.0f; } Gspec_tint.x=1.0f; Gspec_tint.y=1.0f; Gspec_tint.z=1.0f; Gspec_tint2.x=0.0f; Gspec_tint2.y=0.0f; Gspec_tint2.z=0.0f; ci.kspec = vh->gloss; // ci.kspec=.6f; ci.spec = ( float ) vh->spec / 255.0f; // why ? // ci.spec=1.0f; ci.diff = vh->diff; ci.ambient = 1.0f; ci.ambient = vh->shad; ci.mtl = 0; ci.groupID = 0; // ci.depthpass = Gcurpass; ci.killme = 0; ci.restlength = 1.0f; // stand-in shade_a_curve( &ci, &wf ); for( x = 0; x < vh->segs; x++ ) vh->color[x] = wf.color[x]; free_geomWF( &wf ); } int VXtrace( float nearClip, float farClip, VERT rbase, VERT rdir, int shademe, VOXSAMP * vsamp ) { int shademevox = 0; int gotone = 0; int inst; int xxx; VXSHAVEdata *dat; TRACEINFO hr[35]; //,hr2; TRACEINFO hr2[35]; //,hr2; TRACEINFO ihr[35]; //,hr2; shademevox = shademe; vsamp->color.x = 0; vsamp->color.y = 0; vsamp->color.z = 0; vsamp->opacity = 0; vsamp->distance = -1; for( xxx = 0; xxx < 35; xxx++ ) { hr[xxx].din = -1.0f; hr[xxx].flag = 0; } hr[0].total = 0; for( inst = 0; inst < totalhairfiles; inst++ ) { int notrace = 0; double dfC; float fC; dfC = farClip; fC = ( float ) dfC; dat = Gvoxdata[inst]; //if (dat->instancing==0) Shave_Trace( rbase, rdir, dat, dfC, shademe, hr2 ); // integrate the samples together //if (0==1) { int sort1, checkit, movit; for( sort1 = 0; sort1 < hr2[0].total; sort1++ ) { int done = 0; hr2[sort1].instid = inst; for( checkit = 0; checkit < 35; checkit++ ) if( hr2[sort1].flag == 1 ) if( done == 0 ) if( ( ( hr2[sort1].din < hr[checkit].din ) && ( hr2[sort1].flag == 1 ) ) || ( ( hr[checkit].flag == 0 ) && ( hr2[sort1].flag == 1 ) ) ) { for( movit = 35 - 1; movit > checkit; movit-- ) { if( movit > 0 ) hr[movit] = hr[movit - 1]; } hr[checkit] = hr2[sort1]; done = 1; // checkit=35; } } checkit = 0; for( sort1 = 0; sort1 < 35; sort1++ ) if( hr[sort1].flag > 0 ) checkit++; hr[0].total = checkit; // now reverse the order for( sort1 = 0; sort1 < checkit; sort1++ ) { hr2[( checkit - 1 ) - sort1] = hr[sort1]; } for( sort1 = 0; sort1 < checkit; sort1++ ) { hr[sort1] = hr2[sort1]; } hr[0].total = checkit; } } { int x; int max = -1; float mindist = 9999998; float maxdist = 0; // int xx; // TRACEINFO ti; float topacity = 0; VERT totalcolor; float md2; int total2 = 0; int y; int oldt; topacity = 0; totalcolor.x = 0; totalcolor.y = 0; totalcolor.z = 0; mindist = 1000000.0f; topacity = 0; max = hr[0].total; topacity = 0; if( max > 0 ) for( x = 0; x < max; x++ ) if( topacity <= 1.0 ) if( hr[x].flag ) if( hr[x].din > nearClip ) if( hr[x].din < farClip ) { VERT vc, vc1; VERT *vcc; float opp; float opp2; int segn1; opp = hr[x].opacity; opp2 = ( 1.0f - ( ( float ) hr[x].segno / ( float ) dat->voxhair[hr[x].hairno].segs ) ); if (opp2<0.0f) opp2=0.0f; opp*=opp2; topacity += opp; gotone = 1; dat = Gvoxdata[hr[x].instid]; if( hr[x].din < mindist ) mindist = hr[x].din; if( shademevox ) { float uuu; VERT vl, vl1; segn1 = hr[x].segno + 1; if( segn1 > dat->voxhair[hr[x].hairno].segs - 1 ) segn1 = dat->voxhair[hr[x].hairno].segs - 1; vcc= &dat->voxhair[hr[x].hairno].color[hr[x].segno]; vc = (*vcc); if ((vcc->x) == -2 ) // it's being shading, wait { while ((vcc->x) == -2) { int delay; float qd; for (delay=0;delay<30;delay++) { qd=drand98(); } } } if( (vcc->x) == -1 ) { // illuminate_strandVH( &dat->voxhair[hr[x].hairno], // hr[x].hairno ); vcc->x= -2; // to avoid other threads colliding illuminate_strandVH( &dat->voxhair[hr[x].hairno] ); } vc = dat->voxhair[hr[x].hairno].color[hr[x].segno]; vl = dat->voxhair[hr[x].hairno].velocity[hr[x].segno]; vc1 = dat->voxhair[hr[x].hairno].color[segn1]; vl1 = dat->voxhair[hr[x].hairno].velocity[segn1]; uuu = hr[x].u; { float iuuu; iuuu=1.0f-uuu; if (iuuu<0.0f) iuuu=0.0f; vc.x = vc.x * ( iuuu ) + vc1.x * uuu; vc.y = vc.y * ( iuuu ) + vc1.y * uuu; vc.z = vc.z * ( iuuu ) + vc1.z * uuu; vl.x = vl.x * ( iuuu ) + vl1.x * uuu; vl.y = vl.y * ( iuuu ) + vl1.y * uuu; vl.z = vl.z * ( iuuu ) + vl1.z * uuu; } if( vc.x > 1 ) vc.x = 1; if( vc.y > 1 ) vc.y = 1; if( vc.z > 1 ) vc.z = 1; vsamp->velocity = vl; { float iopp; iopp=1.0f-opp; if (iopp<0.0f) iopp=0.0f; totalcolor.x = vc.x * opp + totalcolor.x * ( iopp ); totalcolor.y = vc.y * opp + totalcolor.y * ( iopp ); totalcolor.z = vc.z * opp + totalcolor.z * ( iopp ); } } } if( totalcolor.x > 1 ) totalcolor.x = 1; if( totalcolor.y > 1 ) totalcolor.y = 1; if( totalcolor.z > 1 ) totalcolor.z = 1; if( topacity > 1.0 ) topacity = 1.0f; if( mindist > nearClip ) if( mindist < farClip ) { vsamp->distance = mindist; if( shademevox == 0 ) { totalcolor.x = 0; totalcolor.y = 0; totalcolor.z = 0; } if( shademevox ) { vsamp->color.x = ( float ) totalcolor.x; //*topacity; vsamp->color.y = ( float ) totalcolor.y; //*topacity; vsamp->color.z = ( float ) totalcolor.z; //*topacity; } vsamp->opacity = ( double ) topacity; } } return ( gotone ); } void VXinit( void ) { int x, xx; for( x = 0; x < 255; x++ ) Gvoxdata[x] = NULL; } void VXcreate( void ) { int xx; for( xx = 0; xx < totalhairfiles; xx++ ) { fetch_hair( xx, 0.0 ); Gvoxdata[xx] = ( VXSHAVEdata * ) malloc( sizeof( VXSHAVEdata ) ); Gvoxdata[xx]->totalhairs = 0; VXinit_bound( Gvoxdata[xx], 1 ); } Gtrace = 1; printf( "trace engine is ON\n" ); } void VXclear( void ) { int x, y, z; VXSHAVEdata *dat; int xx; if( Gtrace != 0 ) { for( xx = 0; xx < 255; xx++ ) { dat = Gvoxdata[xx]; if( dat != NULL ) if( dat->totalhairs != 0 ) { int yy; for( yy = 0; yy < dat->totalhairs; yy++ ) { Nfree( dat->voxhair[yy].hv ); Nfree( dat->voxhair[yy].color ); Nfree( dat->voxhair[yy].velocity ); // Nfree(dat->voxhair[yy]); } Nfree( dat->voxhair ); } if( dat != NULL ) for( x = 0; x < VXLIMIT; x++ ) for( y = 0; y < VXLIMIT; y++ ) for( z = 0; z < VXLIMIT; z++ ) { //// if (firstuseVOX!=1) // if (allvox[x+VXLIMIT*y+VXLIMIT*VXLIMIT*z].totalseg!=0) { if( dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].segs != NULL ) //come back here Nfree( dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].segs ); } } Nfree( dat ); } } Gtrace = 0; } // // // * set up the bounding voxel for all hair // * reset all voxel counters // * clear all voxel hairs // // void VXinit_bound( VXSHAVEdata * dat, int wipecolor ) { int x, y, z; VERT vs; int slg; int cc; int q; // int mb; int done = 0; int totalhairs = 0; int tmpt; RENDERHAIR h; // int clone[5]; // int outerloop; // VOXEL boundvox; WFTYPE spl; CURVEINFO cinfo; // local_segs=56; //fdg=fopen("traceme.txt","w"); VERT offstable[8]; init_geomWF( &spl ); offstable[0].x = -1.0; offstable[0].y = -1.0f; offstable[0].z = -1.0f; //offstable[0].x= 0.0 ; offstable[0].y= 0.0f; offstable[0].z= 0.0f; offstable[1].x = 1.0; offstable[1].y = -1.0f; offstable[1].z = -1.0f; offstable[2].x = 1.0; offstable[2].y = -1.0f; offstable[2].z = 1.0f; offstable[3].x = -1.0; offstable[3].y = -1.0f; offstable[3].z = 1.0f; offstable[4].x = -1.0; offstable[4].y = 1.0f; offstable[4].z = -1.0f; offstable[5].x = 1.0; offstable[5].y = 1.0f; offstable[5].z = -1.0f; offstable[6].x = 1.0; offstable[6].y = 1.0f; offstable[6].z = 1.0f; offstable[7].x = -1.0; offstable[7].y = 1.0f; offstable[7].z = 1.0f; for( slg = 0; slg < 5; slg++ ) { dat->haircount[slg] = LOCAL_CNT[slg]; dat->segs[slg] = LOCAL_SEGS[slg]; if( freeze.totalverts > 0 ) dat->segs[slg] = 3; dat->PASSES[slg] = LOCAL_PASSES[slg]; } dat->instancing = 0; if( freeze.totalverts > 0 ) dat->instancing = 1; for( slg = 0; slg < 5; slg++ ) if( dat->instancing == 1 ) dat->haircount[slg] *= freeze.totalverts; //getMAXPASSES(); make_normals( ); init_noise( ); mkbounds( ); restBOUNDLENGTH = BOUNDLENGTH; dat->restBOUNDLENGTH = restBOUNDLENGTH; weight_polys( ); texture_bounds( ); dat->boundvox.bound1.x = 1000000.0f; dat->boundvox.bound1.y = 1000000.0f; dat->boundvox.bound1.z = 1000000.0f; dat->boundvox.bound2.x = -1000000.0f; dat->boundvox.bound2.y = -1000000.0f; dat->boundvox.bound2.z = -1000000.0f; { // for (x=0;xhaircount*PASSES;x++) // if (dat->haircount!=0) { // Nfree(dat->voxhair[x].color); // Nfree(dat->voxhair[x].hv); } for( x = 0; x < 5; x++ ) { dat->clone[x] = ( int ) sliders[25][x].value; if( dat->clone[x] < 1 ) dat->clone[x] = 1; // dat->segs[x]=10; } for( x = 0; x < 5; x++ ) dat->PASSES[x] = LOCAL_PASSES[x]; if( wipecolor ) if( dat->totalhairs != 0 ) { Nfree( dat->voxhair->hv ); Nfree( dat->voxhair->color ); Nfree( dat->voxhair->velocity ); Nfree( dat->voxhair ); } if( wipecolor ) dat->voxhair = ( VOXHAIR * ) malloc( ( dat->haircount[0] * dat->clone[0] * dat->PASSES[0] + dat->haircount[1] * dat->clone[1] * dat->PASSES[1] + dat->haircount[2] * dat->clone[2] * dat->PASSES[2] + dat->haircount[3] * dat->clone[3] * dat->PASSES[3] + dat->PASSES[4] * dat->haircount[4] * dat->clone[4] ) * sizeof( VOXHAIR ) ); //for (x=0;xvoxhair=(VOXHAIR *) malloc (sizeof(VOXHAIR)); // dat->voxhair[x].color=(VERT *) malloc ((local_segs+5)*sizeof(VERT)); // dat->voxhair[x].hv=(VERT *) malloc ((local_segs+5)*sizeof(VERT)); } } // dat->haircount=haircount; for( slg = 0; slg < 5; slg++ ) for( cc = 0; cc < dat->PASSES[slg]; cc++ ) if( dat->instancing == 0 ) { // if (dat->instancing==1) //MAYAmake_a_hair(cc,slg,x,10,&spl,&cinfo); for( x = 0; x < dat->haircount[slg]; x++ ) { // BASEHAIR bh; int f, g; // int rr; VERT offs; offs.x = 0; offs.y = 0; offs.z = 0; gascalr = 1.0f; gascalh = 1.0f; //rr=x % dat->haircount; Gcurpass = cc; Gpass = cc; Gslg = slg; if( dat->instancing == 0 ) MAYAmake_a_curve( cc, slg, x, dat->segs[slg], &spl, &cinfo ); for( q = 0; q < spl.totalverts; q++ ) { spl.v[q].z = -spl.v[q].z; spl.velocity[q].z = -spl.velocity[q].z; spl.vn[q].z = -spl.vn[q].z; } //MAYAmake_a_curve(0,slg,x,dat->segs[slg],&spl,&cinfo); //printf("x = %d slg=%d segs=%d\n",x,slg,dat->segs[slg]); for( f = 0; f < spl.totalfaces; f++ ) { VOXHAIR *vxh; float op = 0; if( dat->PASSES[slg] >= 1 ) op = ( float ) 1.0 / ( float ) ( dat->PASSES[slg] ); op = pow( op, 1.5 ); // if (dat->PASSES[slg]==1) op=1.0f; // op*=.; dat->voxhair[totalhairs].opacity = op; //// h= make_strand(x,offs,local_segs); if( dat->instancing == 0 ) dat->voxhair[totalhairs].segs = dat->segs[slg]; if( dat->instancing == 1 ) dat->voxhair[totalhairs].segs = 3; dat->voxhair[totalhairs].slg = slg; dat->voxhair[totalhairs].hv = ( VERT * ) malloc( ( spl.face_end[f] - spl.face_start[f] ) * sizeof( VERT ) ); if( wipecolor ) dat->voxhair[totalhairs].color = ( VERT * ) malloc( ( spl.face_end[f] - spl.face_start[f] ) * sizeof( VERT ) ); dat->voxhair[totalhairs].velocity = ( VERT * ) malloc( ( spl.face_end[f] - spl.face_start[f] ) * sizeof( VERT ) ); for( y = 0; y < spl.face_end[f] - spl.face_start[f]; y++ ) { g = spl.facelist[y + spl.face_start[f]]; dat->voxhair[totalhairs].hv[y] = spl.v[g]; dat->voxhair[totalhairs].velocity[y] = spl.velocity[g]; // dat->voxhair[totalhairs].color[y]=spl.color[g]; dat->voxhair[totalhairs].color[y].x = -1; dat->voxhair[totalhairs].color[y].y = -1; dat->voxhair[totalhairs].color[y].z = -1; //// h.hv[y]=spl.v[g]; // watch out for overflow // h.hv[y].z= -h.hv[y].z; // voxhair[x].mtl=(unsigned char) h.mtl; // if (h.killme) dat->voxhair[x].killme=1; } dat->voxhair[totalhairs].radbase = cinfo.baserad; dat->voxhair[totalhairs].radtip = cinfo.tiprad; dat->voxhair[totalhairs].colorroot = spl.color[spl.facelist[spl.face_start[f]]]; dat->voxhair[totalhairs].colortip = spl.color[spl.facelist[spl.face_end[f] - 1]]; dat->voxhair[totalhairs].diff = cinfo.diff; dat->voxhair[totalhairs].spec = cinfo.spec; dat->voxhair[totalhairs].gloss = cinfo.kspec; dat->voxhair[totalhairs].shad = cinfo.ambient; dat->voxhair[totalhairs].norm = cinfo.norm; // good to here vxh = &dat->voxhair[totalhairs]; for( y = 0; y < dat->segs[slg]; y++ ) { if( wipecolor ) dat->voxhair[totalhairs].color[y].x = -1; if( dat->boundvox.bound1.x >= vxh->hv[y].x ) dat->boundvox.bound1.x = vxh->hv[y].x; if( dat->boundvox.bound1.y >= vxh->hv[y].y ) dat->boundvox.bound1.y = vxh->hv[y].y; if( dat->boundvox.bound1.z >= vxh->hv[y].z ) dat->boundvox.bound1.z = vxh->hv[y].z; if( dat->boundvox.bound2.x <= vxh->hv[y].x ) dat->boundvox.bound2.x = vxh->hv[y].x; if( dat->boundvox.bound2.y <= vxh->hv[y].y ) dat->boundvox.bound2.y = vxh->hv[y].y; if( dat->boundvox.bound2.z <= vxh->hv[y].z ) dat->boundvox.bound2.z = vxh->hv[y].z; } totalhairs++; } // face count } } tmpt = 0; dat->totalhairs = totalhairs; dat->boundvoxlength = sqrt( ( dat->boundvox.bound2.x - dat->boundvox.bound1.x ) * ( dat->boundvox.bound2.x - dat->boundvox.bound1.x ) + ( dat->boundvox.bound2.y - dat->boundvox.bound1.y ) * ( dat->boundvox.bound2.y - dat->boundvox.bound1.y ) + ( dat->boundvox.bound2.z - dat->boundvox.bound1.z ) * ( dat->boundvox.bound2.z - dat->boundvox.bound1.z ) ); //printf("%f\n",dat->boundvoxlength); //printf("%f %f %f %f %f %f\n", // dat->boundvox.bound1.x, // dat->boundvox.bound1.y, // dat->boundvox.bound1.z, // dat->boundvox.bound2.x, // dat->boundvox.bound2.y, // dat->boundvox.bound2.z); vs.x = dat->boundvox.bound2.x - dat->boundvox.bound1.x; vs.y = dat->boundvox.bound2.y - dat->boundvox.bound1.y; vs.z = dat->boundvox.bound2.z - dat->boundvox.bound1.z; vs.x /= ( float ) ( VXLIMIT ); vs.y /= ( float ) ( VXLIMIT ); vs.z /= ( float ) ( VXLIMIT ); // clear the voxels // and set bounds for them for( x = 0; x < VXLIMIT; x++ ) for( y = 0; y < VXLIMIT; y++ ) for( z = 0; z < VXLIMIT; z++ ) { //// if (firstuseVOX!=1) // if (allvox[x+VXLIMIT*y+VXLIMIT*VXLIMIT*z].totalseg!=0) { // if (dat->allvox[x+VXLIMIT*y+VXLIMIT*VXLIMIT*z].segs!=NULL) //come back here // Nfree(dat->allvox[x+VXLIMIT*y+VXLIMIT*VXLIMIT*z].segs); } //// if (firstuseVOX==1) dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].segs = NULL; // if ((allvox[x+VXLIMIT*y+VXLIMIT*VXLIMIT*z])!=NULL) allvox[x+VXLIMIT*y+VXLIMIT*VXLIMIT*z]=NULL; dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].totalseg = 0; dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound1.x = dat->boundvox.bound1.x + vs.x * ( float ) x; // -vs.x/2; dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound1.y = dat->boundvox.bound1.y + vs.y * ( float ) y; // -vs.y/2; dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound1.z = dat->boundvox.bound1.z + vs.z * ( float ) z; // -vs.z/2; dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound2.x = dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound1.x + vs.x; // +vs.x; dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound2.y = dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound1.y + vs.y; // +vs.y; dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound2.z = dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].bound1.z + vs.z; // +vs.z; } firstuseVOX = 0; // now figure out the totals in each vox // dat->boundvox=boundvox; done = 0; for( x = 0; x < dat->totalhairs; x++ ) { VOXHAIR *vh; int overflow = 0; int lastx, lasty, lastz; // float flastx,flasty,flastz; vh = &dat->voxhair[x]; lastx = 9999; lasty = 9999; lastz = 9999; if( dat->segs[dat->voxhair[x].slg] > 1 ) for( y = 0; y < dat->segs[dat->voxhair[x].slg] - 1; y++ ) { float walk; float radrad; int xxx, yyy, zzz; int xxx1, yyy1, zzz1; float fxxx, fyyy, fzzz; float fxxx1, fyyy1, fzzz1; float dx, dy, dz, dd; VERT voxrad; overflow = 0; if( vh->radbase >= vh->radtip ) radrad = vh->radbase; if( vh->radtip > vh->radbase ) radrad = vh->radtip; voxrad.x = ( ( ( radrad ) / ( dat->boundvox.bound2.x - dat->boundvox.bound1.x ) ) * ( float ) ( VXLIMIT ) ); voxrad.y = ( ( ( radrad ) / ( dat->boundvox.bound2.y - dat->boundvox.bound1.y ) ) * ( float ) ( VXLIMIT ) ); voxrad.z = ( ( ( radrad ) / ( dat->boundvox.bound2.z - dat->boundvox.bound1.z ) ) * ( float ) ( VXLIMIT ) ); if( dat->instancing == 1 ) { voxrad.x = 0; voxrad.y = 0; voxrad.z = 0; } fxxx = ( ( ( vh->hv[y].x - dat->boundvox.bound1.x ) / ( dat->boundvox.bound2.x - dat->boundvox.bound1.x ) ) * ( float ) ( VXLIMIT ) ); fyyy = ( ( ( vh->hv[y].y - dat->boundvox.bound1.y ) / ( dat->boundvox.bound2.y - dat->boundvox.bound1.y ) ) * ( float ) ( VXLIMIT ) ); fzzz = ( ( ( vh->hv[y].z - dat->boundvox.bound1.z ) / ( dat->boundvox.bound2.z - dat->boundvox.bound1.z ) ) * ( float ) ( VXLIMIT ) ); xxx = ( int ) floor( fxxx ); yyy = ( int ) floor( fyyy ); zzz = ( int ) floor( fzzz ); fxxx1 = ( ( ( vh->hv[y + 1].x - dat->boundvox.bound1.x ) / ( dat->boundvox.bound2.x - dat->boundvox.bound1.x ) ) * ( float ) ( VXLIMIT ) ); fyyy1 = ( ( ( vh->hv[y + 1].y - dat->boundvox.bound1.y ) / ( dat->boundvox.bound2.y - dat->boundvox.bound1.y ) ) * ( float ) ( VXLIMIT ) ); fzzz1 = ( ( ( vh->hv[y + 1].z - dat->boundvox.bound1.z ) / ( dat->boundvox.bound2.z - dat->boundvox.bound1.z ) ) * ( float ) ( VXLIMIT ) ); xxx1 = ( int ) floor( fxxx1 ); yyy1 = ( int ) floor( fyyy1 ); zzz1 = ( int ) floor( fzzz1 ); if( voxrad.x > .5 ) overflow = 1; if( voxrad.y > .5 ) overflow = 1; if( voxrad.z > .5 ) overflow = 1; overflow = 1; if( ( xxx != xxx1 ) || ( yyy != yyy1 ) || ( zzz != zzz1 ) ) overflow = 1; if( y == 0 ) overflow = 0; dx = ( float ) ( fxxx1 - fxxx ); dy = ( float ) ( fyyy1 - fyyy ); dz = ( float ) ( fzzz1 - fzzz ); // if overflow == 1 then the segment is longer than a voxel dd = sqrt( dx * dx + dy * dy + dz * dz ); if( dd > 0 ) { dx /= dd; dy /= dd; dz /= dd; } walk = 0.0f; // for (walk=0;walk<=dd;walk+=1.0) { int azx, azy, azz; int xx, yy, zz; int mbx1, mby1, mbz1; int mbx2, mby2, mbz2; VERT low, high; float fxx, fyy, fzz; fxx = ( dx * walk ) + fxxx; fyy = ( dy * walk ) + fyyy; fzz = ( dz * walk ) + fzzz; xx = ( int ) fxx; yy = ( int ) fyy; zz = ( int ) fzz; if( fxxx < fxxx1 ) { low.x = fxxx; high.x = fxxx1; } if( fxxx1 <= fxxx ) { low.x = fxxx1; high.x = fxxx; } if( fyyy < fyyy1 ) { low.y = fyyy; high.y = fyyy1; } if( fyyy1 <= fyyy ) { low.y = fyyy1; high.y = fyyy; } if( fzzz < fzzz1 ) { low.z = fzzz; high.z = fzzz1; } if( fzzz1 <= fzzz ) { low.z = fzzz1; high.z = fzzz; } // make a box to fill that's the size of the radius in voxels mbx1 = ( int ) floor( low.x - voxrad.x * 2.0f ); mby1 = ( int ) floor( low.y - voxrad.y * 2.0f ); mbz1 = ( int ) floor( low.z - voxrad.z * 2.0f ); mbx2 = ( int ) ceil( high.x + voxrad.x * 2.0f ); mby2 = ( int ) ceil( high.y + voxrad.y * 2.0f ); mbz2 = ( int ) ceil( high.z + voxrad.z * 2.0f ); // if ((mbx1>=0)&&(mbx2=0)&&(mby2=0)&&(mbz2= 0 ) && ( azx < VXLIMIT ) && ( azy >= 0 ) && ( azy < VXLIMIT ) && ( azz >= 0 ) && ( azz < VXLIMIT ) ) { int addr; // if ((azx>=0)&&(azx=0)&&(azy=0)&&(azzallvox[addr].totalseg++; } } // end box fill } // end walk } // end y (hair) } // end tags (all hair) // now allocate them { int tt; tt = 0; for( x = 0; x < VXLIMIT; x++ ) for( y = 0; y < VXLIMIT; y++ ) for( z = 0; z < VXLIMIT; z++ ) { int addr; addr = x + VXLIMIT * y + VXLIMIT * VXLIMIT * z; dat->allvox[addr].segs = ( HSEG * ) malloc( ( dat->allvox[x + VXLIMIT * y + VXLIMIT * VXLIMIT * z].totalseg + 1 ) * sizeof( HSEG ) ); dat->allvox[addr].totalseg = 0; } } for( x = 0; x < dat->totalhairs; x++ ) { VOXHAIR *vh; float radrad; int overflow = 0; int lastx, lasty, lastz; VERT voxrad; VERT voxdim; // float flastx,flasty,flastz; vh = &dat->voxhair[x]; lastx = 9999; lasty = 9999; lastz = 9999; voxdim.x = dat->boundvox.bound2.x - dat->boundvox.bound1.x; voxdim.y = dat->boundvox.bound2.y - dat->boundvox.bound1.y; voxdim.z = dat->boundvox.bound2.z - dat->boundvox.bound1.z; voxdim.x /= ( float ) VXLIMIT; voxdim.y /= ( float ) VXLIMIT; voxdim.z /= ( float ) VXLIMIT; if( vh->radbase >= vh->radtip ) radrad = vh->radbase; if( vh->radtip > vh->radbase ) radrad = vh->radtip; voxrad.x = // ( ( ( radrad ) / ( voxdim.x ) ); //*(float)(VXLIMIT)); voxrad.y = // ( ( ( radrad ) / ( voxdim.y ) ); //*(float)(VXLIMIT)); voxrad.z = // ( ( ( radrad ) / ( voxdim.z ) ); //*(float)(VXLIMIT)); { float rad; float d; VERT tm; float o,h; // now, we're going to calculate the base radius in pixels - this is approximate tm=vh->hv[0]; // base of the hair h=Distance(tm,LWCamOPEN.wpos); if (h>0.0f) { float s; // FILE *fp; //LWcamOPEN.xres=300; s=sin(((float)LWCamOPEN.fov/(float)LWCamOPEN.xres)*(6.283f/360.0f)); // assumes an fov of 90 o=s*h; // 1 pixel in worldspace vh->minrad=o*2; // fp=fopen("c:\\diag.txt","w"); // fprintf (fp,"xres = %d wpos = %f %f %f o = %f\n",LWCamOPEN.xres, // LWCamOPEN.wpos.x,LWCamOPEN.wpos.y,LWCamOPEN.wpos.z,o); // fclose(fp); } } if( dat->segs[vh->slg] > 1 ) for( y = 0; y < dat->segs[vh->slg] - 1; y++ ) { float walk; int xxx, yyy, zzz; int xxx1, yyy1, zzz1; float fxxx, fyyy, fzzz; float fxxx1, fyyy1, fzzz1; float dx, dy, dz, dd; int lastxx = 999, lastyy = 999, lastzz = 999; int minor; overflow = 0; fxxx = ( // ( ( vh->hv[y].x - dat->boundvox.bound1.x ) / ( voxdim.x ) ); //*(float)(VXLIMIT)); fyyy = ( // ( ( vh->hv[y].y - dat->boundvox.bound1.y ) / ( voxdim.y ) ); //*(float)(VXLIMIT)); fzzz = ( // ( ( vh->hv[y].z - dat->boundvox.bound1.z ) / ( voxdim.z ) ); //*(float)(VXLIMIT)); xxx = ( int ) floor( fxxx ); yyy = ( int ) floor( fyyy ); zzz = ( int ) floor( fzzz ); fxxx1 = ( // ( ( vh->hv[y + 1].x - dat->boundvox.bound1.x ) / ( voxdim.x ) ); // (dat->boundvox.bound2.x-dat->boundvox.bound1.x) // )*(float)(VXLIMIT)); fyyy1 = ( // ( ( vh->hv[y + 1].y - dat->boundvox.bound1.y ) / ( voxdim.y ) ); // (dat->boundvox.bound2.y-dat->boundvox.bound1.y) // )*(float)(VXLIMIT)); fzzz1 = ( // ( ( vh->hv[y + 1].z - dat->boundvox.bound1.z ) / ( voxdim.z ) ); // (dat->boundvox.bound2.z-dat->boundvox.bound1.z) // )*(float)(VXLIMIT)); xxx1 = ( int ) floor( fxxx1 ); yyy1 = ( int ) floor( fyyy1 ); zzz1 = ( int ) floor( fzzz1 ); //if (voxrad>1.0) overflow=1.0 if( voxrad.x > .5 ) overflow = 1; if( voxrad.y > .5 ) overflow = 1; if( voxrad.z > .5 ) overflow = 1; overflow = 1; if( ( xxx != xxx1 ) || ( yyy != yyy1 ) || ( zzz != zzz1 ) ) overflow = 1; if( y == 0 ) overflow = 0; dx = ( float ) ( fxxx1 - fxxx ); dy = ( float ) ( fyyy1 - fyyy ); dz = ( float ) ( fzzz1 - fzzz ); // if overflow == 1 then the segment is longer than a voxel dd = sqrt( dx * dx + dy * dy + dz * dz ); if( dd > 0 ) { dx /= dd; dy /= dd; dz /= dd; } walk = 0.0f; // for (walk=0;walk<=dd;walk+=1.0) { int azx, azy, azz; // int axx,ayy,azz; int xx, yy, zz; int mbx1, mby1, mbz1; int mbx2, mby2, mbz2; float fxx, fyy, fzz; VERT low, high; fxx = ( dx * walk ) + fxxx; fyy = ( dy * walk ) + fyyy; fzz = ( dz * walk ) + fzzz; xx = ( int ) fxx; yy = ( int ) fyy; zz = ( int ) fzz; if( fxxx < fxxx1 ) { low.x = fxxx; high.x = fxxx1; } if( fxxx1 <= fxxx ) { low.x = fxxx1; high.x = fxxx; } if( fyyy < fyyy1 ) { low.y = fyyy; high.y = fyyy1; } if( fyyy1 <= fyyy ) { low.y = fyyy1; high.y = fyyy; } if( fzzz < fzzz1 ) { low.z = fzzz; high.z = fzzz1; } if( fzzz1 <= fzzz ) { low.z = fzzz1; high.z = fzzz; } // make a box to fill that's the size of the radius in voxels mbx1 = ( int ) floor( low.x - voxrad.x * 2.0f ); mby1 = ( int ) floor( low.y - voxrad.y * 2.0f ); mbz1 = ( int ) floor( low.z - voxrad.z * 2.0f ); mbx2 = ( int ) ceil( high.x + voxrad.x * 2.0f ); mby2 = ( int ) ceil( high.y + voxrad.y * 2.0f ); mbz2 = ( int ) ceil( high.z + voxrad.z * 2.0f ); // if ((lastxx!=xx)||(lastyy!=yy)||(lastzz!=zz)) for( azx = mbx1; azx <= mbx2; azx++ ) for( azy = mby1; azy <= mby2; azy++ ) for( azz = mbz1; azz <= mbz2; azz++ ) if( ( azx >= 0 ) && ( azx < VXLIMIT ) && ( azy >= 0 ) && ( azy < VXLIMIT ) && ( azz >= 0 ) && ( azz < VXLIMIT ) ) { int addr; int dont = 0; int checkvox; lastxx = xx; lastyy = yy; lastzz = zz; addr = azx + azy * VXLIMIT + azz * VXLIMIT * VXLIMIT; // if ((azx>=0)&&(azx=0)&&(azy=0)&&(azzallvox[addr]; { av->segs[av->totalseg].segno = y; av->segs[av->totalseg].hairno = x; av->totalseg++; } } // end check vxlimit } } // end walk } // end y (hair) } // end tags (all hair) LWcam = LWCamOPEN; // remember to interpolate this stuff free_geomWF( &spl ); } VERT Vnorm( VERT ); void Shave_Trace( VERT rbase, VERT rdir, VXSHAVEdata * dat, double fC, int shademe, TRACEINFO * tracestack ) { // VOXEL boundvox; // int transplayers; // TRACEINFO closest_trace; int x; //int slg; VOXEL *vx; VERT pp; //HVOXRET tracestack; TRACEINFO hbb; //int local_segs; int start_dist = 0; int done = 0; int dontkill = 1; int loop = 0; int outside = 0; TRACEINFO traceinfo; TRIPLEINT hitvox[VXLIMIT * 2]; int hitvoxtotal = 0; VERT center, onevox; int totaltrace = 0; int TStotaltrace = 0; float total_opacity = 0; char hitbox = 0; VERT sl; int xxx, yyy, zzz; float fxxx, fyyy, fzzz, fxxx1, fyyy1, fzzz1; int lastx = 999, lasty = 999, lastz = 999; // float bl; int cnt; //TRACEINFO closest_trace; // for (bb=0;bbboundvox; // MAXPASSES=dat->PASSES; hmmmm /// transplayers=dat->PASSES; hmmmm // local_segs=56; // if (dat->segs) local_segs=5; // haircount=dat->haircount; hmmm pp = rbase; rdir = Vnorm( rdir ); tracestack[0].total = 0; for( x = 0; x < 22; x++ ) { tracestack[x].din = ( float ) 99999999; tracestack[x].flag = 0; tracestack[x].hairno = -1; } //pp.x+=rdir.x*start_dist; //pp.y+=rdir.y*start_dist; //pp.z+=rdir.z*start_dist; // is the base outside the box? // if so, test for intersection if( ( pp.x >= dat->boundvox.bound1.x ) && ( pp.y >= dat->boundvox.bound1.y ) && ( pp.z >= dat->boundvox.bound1.z ) && ( pp.x <= dat->boundvox.bound2.x ) && ( pp.y <= dat->boundvox.bound2.y ) && ( pp.z <= dat->boundvox.bound2.z ) ) // it's inside the box hitbox = 1; if( hitbox == 0 ) { { // if (shademe==1) //printf ("pp = %f %f %f dir = %f %f %f\n",pp.x,pp.y,pp.z,rdir.x,rdir.y,rdir.z); hbb = raybox( pp, rdir, dat->boundvox.bound1, dat->boundvox.bound2 ); } hitbox = hbb.flag; pp = hbb.cin; } hitvoxtotal = 0; done = 0; //itbox=1; if( hitbox ) { // TRACEINFO traceinfo[2]; // VERT tov; VERT pp2, pp3; //printf("hitbox\n"); done = 0; pp2 = pp; fxxx = ( ( ( pp2.x - dat->boundvox.bound1.x ) / ( dat->boundvox.bound2.x - dat->boundvox.bound1.x ) ) * ( float ) ( VXLIMIT ) ); fyyy = ( ( ( pp2.y - dat->boundvox.bound1.y ) / ( dat->boundvox.bound2.y - dat->boundvox.bound1.y ) ) * ( float ) ( VXLIMIT ) ); fzzz = ( ( ( pp2.z - dat->boundvox.bound1.z ) / ( dat->boundvox.bound2.z - dat->boundvox.bound1.z ) ) * ( float ) ( VXLIMIT ) ); pp3.x = ( float ) fxxx; pp3.y = ( float ) fyyy; pp3.z = ( float ) fzzz; pp2.x = pp.x + rdir.x * dat->boundvoxlength; pp2.y = pp.y + rdir.y * dat->boundvoxlength; pp2.z = pp.z + rdir.z * dat->boundvoxlength; fxxx1 = ( ( ( pp2.x - dat->boundvox.bound1.x ) / ( dat->boundvox.bound2.x - dat->boundvox.bound1.x ) ) * ( float ) ( VXLIMIT ) ); fyyy1 = ( ( ( pp2.y - dat->boundvox.bound1.y ) / ( dat->boundvox.bound2.y - dat->boundvox.bound1.y ) ) * ( float ) ( VXLIMIT ) ); fzzz1 = ( ( ( pp2.z - dat->boundvox.bound1.z ) / ( dat->boundvox.bound2.z - dat->boundvox.bound1.z ) ) * ( float ) ( VXLIMIT ) ); // if (fxxx1>VXLIMIT) fxxx1=(float)VXLIMIT+(fxxx1-floor(fxxx1)); // if (fyyy1>VXLIMIT) fyyy1=(float)VXLIMIT+(fyyy1-floor(fyyy1)); // if (fzzz1>VXLIMIT) fzzz1=(float)VXLIMIT+(fzzz1-floor(fzzz1)); // if (fxxx1<0) fxxx1=(float)-(fxxx1-floor(fxxx1)); // if (fyyy1<0) fyyy1=(float)-(fyyy1-floor(fyyy1)); // if (fzzz1<0) fzzz1=(float)-(fzzz1-floor(fzzz1)); sl.x = ( float ) ( fxxx1 - fxxx ); sl.y = ( float ) ( fyyy1 - fyyy ); sl.z = ( float ) ( fzzz1 - fzzz ); sl = Vnorm( sl ); //sl.x = -sl.x; //sl.y = -sl.y; //sl.z = -sl.z; hitvoxtotal = 0; // pp2=pp; // pp3.x-=sl.x*1; // pp3.y-=sl.y*1; // pp3.z-=sl.z*1; cnt = 0; done = 0; while( done < 2 ) { float ddx, ddy, ddz; float distclip; xxx = ( int ) floor( pp3.x ); yyy = ( int ) floor( pp3.y ); zzz = ( int ) floor( pp3.z ); if( !( ( xxx == lastx ) && ( yyy == lasty ) & ( zzz == lastz ) ) ) if( ( xxx >= 0 ) && ( yyy >= 0 ) && ( zzz >= 0 ) && ( xxx < VXLIMIT ) && ( yyy < VXLIMIT ) && ( zzz < VXLIMIT ) ) { int hv; vx = &dat->allvox[xxx + yyy * VXLIMIT + zzz * VXLIMIT * VXLIMIT]; center.x = ( vx->bound2.x + vx->bound1.x ) / 2.0f; center.y = ( vx->bound2.y + vx->bound1.y ) / 2.0f; center.z = ( vx->bound2.z + vx->bound1.z ) / 2.0f; ddx = center.x - rbase.x; ddy = center.y - rbase.y; ddz = center.z - rbase.z; // if (0==1) // ddx=(pp3.x*(dat->boundvox.bound2.x-dat->boundvox.bound1.x)+dat->boundvox.bound1.x) // -rbase.x; // ddy=(pp3.y*(dat->boundvox.bound2.y-dat->boundvox.bound1.y)+dat->boundvox.bound1.y) // -rbase.y; // ddz=(pp3.z*(dat->boundvox.bound2.z-dat->boundvox.bound1.z)+dat->boundvox.bound1.z) // -rbase.z; distclip = sqrt( ddx * ddx + ddy * ddy + ddz * ddz ); // if (distclip>(float)fC) done++; hv = hitvoxtotal - 1; if( hv < 0 ) hv = 0; // if (((xxx!=hitvox[hv].x)|| // (yyy!=hitvox[hv].y)|| // (zzz!=hitvox[hv].z))||(hitvoxtotal==0)) { hitvox[hitvoxtotal].x = xxx; hitvox[hitvoxtotal].y = yyy; hitvox[hitvoxtotal].z = zzz; hitvoxtotal++; } lastx = xxx; lasty = yyy; lastz = zzz; } if( !( ( xxx >= 0 ) && ( yyy >= 0 ) && ( zzz >= 0 ) && ( xxx < VXLIMIT ) && ( yyy < VXLIMIT ) && ( zzz < VXLIMIT ) ) ) { loop++; // if (loop>4) // give up done += 1; } if( loop > VXLIMIT * 2 ) done += 2; // loop++; pp3.x += sl.x; pp3.y += sl.y; pp3.z += sl.z; } } // // now visit all the tagged voxels and trace some cylenders until we hit one // { // int traceit[30]; int a = 0; // int xx; // int gothit[30]; int sumtrace = 0; done = 0; // closest_trace->flag=0; total_opacity = 0; totaltrace = 0; TStotaltrace = 0; // for (x=0;x<30;x++) gothit[x]=0; // for (x=0;x<30;x++) traceit[x]=0; dontkill = 1; if( hitbox ) if( hitvoxtotal > 0 ) while( done < 4 ) { // new voxel if( ( hitvox[a].x >= 0 ) && ( hitvox[a].x < VXLIMIT ) && ( hitvox[a].y >= 0 ) && ( hitvox[a].y < VXLIMIT ) && ( hitvox[a].z >= 0 ) && ( hitvox[a].z < VXLIMIT ) ) { vx = &dat->allvox[hitvox[a].x + hitvox[a].y * VXLIMIT + hitvox[a].z * VXLIMIT * VXLIMIT]; if( vx->totalseg > 0 ) { // int y; int hn; int thisseg, nextseg; // trace all the pills in the voxel for( x = 0; x < vx->totalseg; x++ ) { hn = vx->segs[x].hairno; if( dat->instancing == 1 ) if( hn < dat->totalhairs ) { float crad; float sg; VERT cbase, cdir; float clen; VERT tmpvert; VOXHAIR *vhr; double uu, vv; WFTYPE csurf; vhr = &dat->voxhair[hn]; thisseg = 0; init_geomWF( &csurf ); traceinfo.flag = 0; traceinfo.din = ray_trace( &rbase, &rdir, &csurf, &uu, &vv ); traceinfo.flag = 0; traceinfo.segno = 0; if( traceinfo.din >= 0 ) { traceinfo.flag = 1; traceinfo.dout = traceinfo.din; } if( traceinfo.flag ) { TRACEINFO *ti; // VERT tmpcolor; float bary[3]; float iuu; float ivv; ivv=1.0f-vv; if (ivv<0.0f) ivv=0.0f; iuu=1.0f-uu; if (iuu<0.0f) iuu=0.0f; ti = &traceinfo; // traceinfo.color.x = ( vhr->color[1].x * ( float ) uu + vhr->color[0].x * ( 1.0f - ( float ) uu ) ) * ( 1.0f - ( float ) vv ) + ( vhr->color[2].x * ( float ) uu + vhr->color[0].x * ( 1.0f - ( float ) uu ) ) * ( float ) vv; // traceinfo.color.y = ( vhr->color[1].x * ( float ) uu + vhr->color[0].y * ( 1.0f - ( float ) uu ) ) * ( 1.0f - ( float ) vv ) + ( vhr->color[2].y * ( float ) uu + vhr->color[0].y * ( 1.0f - ( float ) uu ) ) * ( float ) vv; // traceinfo.color.z = ( vhr->color[1].x * ( float ) uu + vhr->color[0].z * ( 1.0f - ( float ) uu ) ) * ( 1.0f - ( float ) vv ) + ( vhr->color[2].z * ( float ) uu + vhr->color[0].z * ( 1.0f - ( float ) uu ) ) * ( float ) vv; traceinfo.color.x = ( vhr->color[1].x * ( float ) uu + vhr->color[0].x * ( iuu ) ) * ( ivv ) + ( vhr->color[2].x * ( float ) uu + vhr->color[0].x * ( iuu ) ) * ( float ) vv; traceinfo.color.y = ( vhr->color[1].y * ( float ) uu + vhr->color[0].y * ( iuu ) ) * ( ivv ) + ( vhr->color[2].y * ( float ) uu + vhr->color[0].y * ( iuu ) ) * ( float ) vv; traceinfo.color.z = ( vhr->color[1].z * ( float ) uu + vhr->color[0].z * ( iuu ) ) * ( ivv ) + ( vhr->color[2].z * ( float ) uu + vhr->color[0].z * ( iuu ) ) * ( float ) vv; traceinfo.opacity = vhr->opacity; if( shademe == 0 ) traceinfo.opacity /= 2.0f; } traceinfo.diff = vhr->diff; traceinfo.spec = vhr->spec; traceinfo.gloss = vhr->gloss; traceinfo.shad = vhr->shad; traceinfo.opacity = vhr->opacity; if( traceinfo.shad > 1.0 ) traceinfo.shad = 1.0f; if( traceinfo.shad < 0.0 ) traceinfo.shad = 0.0f; if( traceinfo.diff > 1.0 ) traceinfo.diff = 1.0f; if( traceinfo.diff < 0.0 ) traceinfo.diff = 0.0f; if( ( double ) traceinfo.din < fC ) if( traceinfo.flag ) if( traceinfo.din > 0 ) { int q; int ismin = -1; if( TStotaltrace > 0 ) for( q = 0; q < TStotaltrace; q++ ) { if( tracestack[q].hairno == hn ) // looking for a matching sample { ismin = 1; if( tracestack[q].din > traceinfo.din ) if( traceinfo.din < fC ) { tracestack[q] = traceinfo; } } } if( TStotaltrace < ( 35 - 1 ) ) if( ismin < 0 ) // didn't find one, so add it to the stack if( traceinfo.din < fC ) { if( TStotaltrace > 0 ) total_opacity += traceinfo.opacity; tracestack[TStotaltrace] = traceinfo; TStotaltrace++; } // if (TStotaltrace>=34) // { // done+=4; // } } } if( dat->instancing == 0 ) if( hn < dat->totalhairs ) { float crad; float sg; VERT cbase, cdir; float clen; VERT tmpvert; VOXHAIR *vhr; float omult=1.0f; vhr = &dat->voxhair[hn]; thisseg = vx->segs[x].segno; nextseg = thisseg + 1; if( thisseg < dat->segs[vhr->slg] - 1 ) { float isg=0.0f; sg = ( ( float ) thisseg / ( float ) dat->segs[dat->voxhair[hn].slg] ); if (sg>1.0f) sg=1.0f; if (sg<0.0f) sg=0.0f; // possibly the fix for == rad crash? isg=1.0f-sg; if (isg<0.0f) isg=0.0f; cbase = vhr->hv[thisseg]; tmpvert = vhr->hv[nextseg]; cdir.x = tmpvert.x - cbase.x; cdir.y = tmpvert.y - cbase.y; cdir.z = tmpvert.z - cbase.z; clen = sqrt( cdir.x * cdir.x + cdir.y * cdir.y + cdir.z * cdir.z ); cdir = Vnorm( cdir ); crad = ( vhr->radbase ) * ( isg ) + vhr->radtip * sg; if (cradminrad) { omult=crad/vhr->minrad; crad=vhr->minrad; } // let's look into passes later; traceinfo.flag = 0; // crad*=2.0f; trace_pill( rbase, rdir, cbase, cdir, crad, clen, &traceinfo ); //if (instancing==1) // trace_poly(rbase,rdir,cbase,cdir,crad,clen,&traceinfo); traceinfo.segno = thisseg; traceinfo.hairno = hn; traceinfo.dout = traceinfo.din + crad; if( traceinfo.flag ) { TRACEINFO *ti; // VERT tmpcolor; float uu; float u1; float iuu; ti = &traceinfo; //printf("hit one\n"); u1 = ( float ) ( ti->segno ) / ( float ) ( dat->segs[dat->voxhair[ti->hairno].slg] ); // uu*=uu; uu = ti->u; iuu=1.0f-uu; if (iuu<0.0f) iuu=0.0f; // tmpcolor.x=dat->voxhair[ti.hairno].colorroot.x*(1.0f-uu)+ // dat->voxhair[ti.hairno].colorroot.x*uu; // tmpcolor.y=dat->voxhair[ti.hairno].colorroot.y*(1.0f-uu)+ // dat->voxhair[ti.hairno].colorroot.x*uu; // tmpcolor.z=dat->voxhair[ti.hairno].colorroot.z*(1.0f-uu)+ // dat->voxhair[ti.hairno].colorroot.z*uu; // traceinfo.color.x=vhr->color[nextseg].x*uu+vhr->color[ti->segno].x*(1.0f-uu); // traceinfo.color.y=vhr->color[nextseg].y*uu+vhr->color[ti->segno].y*(1.0f-uu); // traceinfo.color.z=vhr->color[nextseg].z*uu+vhr->color[ti->segno].z*(1.0f-uu); traceinfo.color = vhr->color[ti->segno]; // just looking to see if it needs shading traceinfo.velocity.x = vhr->velocity[nextseg].x * uu + vhr->velocity[ti->segno].x * ( iuu ); traceinfo.velocity.y = vhr->velocity[nextseg].y * uu + vhr->velocity[ti->segno].y * ( iuu ); traceinfo.velocity.z = vhr->velocity[nextseg].z * uu + vhr->velocity[ti->segno].z * ( iuu ); traceinfo.opacity = vhr->opacity; if( shademe == 0 ) traceinfo.opacity /= 2.0f; } traceinfo.diff = vhr->diff; traceinfo.spec = vhr->spec; traceinfo.gloss = vhr->gloss; traceinfo.shad = vhr->shad; traceinfo.opacity = vhr->opacity*omult; if( traceinfo.shad > 1.0 ) traceinfo.shad = 1.0f; if( traceinfo.shad < 0.0 ) traceinfo.shad = 0.0f; if( traceinfo.diff > 1.0 ) traceinfo.diff = 1.0f; if( traceinfo.diff < 0.0 ) traceinfo.diff = 0.0f; if( ( double ) traceinfo.din < fC ) if( traceinfo.flag ) if( traceinfo.din > 0 ) { int q; int ismin = -1; if( TStotaltrace > 0 ) for( q = 0; q < TStotaltrace; q++ ) { if( tracestack[q].hairno == hn ) // looking for a matching sample { ismin = 1; if( tracestack[q].din > traceinfo.din ) if( traceinfo.din < fC ) { tracestack[q] = traceinfo; } } } if( TStotaltrace < ( 35 - 1 ) ) if( ismin < 0 ) // didn't find one, so add it to the stack if( traceinfo.din < fC ) { if( TStotaltrace > 0 ) total_opacity += traceinfo.opacity; tracestack[TStotaltrace] = traceinfo; TStotaltrace++; } // if (TStotaltrace>=34) // { // done+=4; // } } } } } // THIS SEG } // hn < TOTALHAIRS } // done x a++; // if (shademe==1) if( total_opacity > 1.0f ) done += 4; // accelleration if( a == hitvoxtotal ) done = 4; } // done WHILE } // DONE nothing } // end total inst tracestack[0].total = TStotaltrace; //return (tracestack); } // the return is the compressed size (in chars) // the input size is the uncompressed size (in chars) int compress_float( unsigned char *buf, int size, unsigned char *outdata ) { int ptr = 0; int blocksize; unsigned char f4[4]; unsigned char lastchar = 0; int in = 0, out = 0; int outdatasize = 0; int mode = 0, q = 0, t = 0; int totalout = 0; lastchar = buf[0]; ptr = 0; // find a block while( ptr < size ) { mode = 0; in = ptr; ptr++; blocksize = 1; lastchar = buf[ptr]; while( ( blocksize < 127 ) && ( lastchar == buf[ptr] ) ) { blocksize++; ptr++; lastchar = buf[ptr - 1]; } out = ptr; // number of consecutive non repeating numbers if( blocksize == 1 ) // the next number is different { mode = 1; // repeat } outdatasize += blocksize + 1; } outdata = ( unsigned char * ) malloc( outdatasize * sizeof( unsigned char ) ); // doit again for real ptr = 0; outdatasize = 0; totalout = 0; while( ptr < size ) { int add; in = ptr; ptr++; mode = 0; blocksize = 1; lastchar = buf[ptr]; while( ( blocksize < 127 ) && ( lastchar == buf[ptr] ) ) { blocksize++; ptr++; lastchar = buf[ptr - 1]; } out = ptr; // number of consecutive non repeating numbers if( blocksize == 1 ) // the next number is different { mode = 1; // repeat } outdata[totalout] = ( unsigned char ) blocksize + ( mode << 7 ); add = 1 + totalout; for( q = 0; q < blocksize; q++ ) { outdata[add] = buf[ptr]; add++; } totalout += blocksize + 1; } return ( outdatasize ); } void SHAVEinit_hairtype( HAIRTYPE * geom ) { geom->totalverts = 0; geom->totalfverts = 0; geom->totalfaces = 0; geom->facelist = NULL; geom->face_start = NULL; geom->face_end = NULL; geom->v = NULL; geom->surfNorm = NULL; geom->uvw = NULL; geom->uvw2 = NULL; geom->velocity = NULL; geom->colorroot = NULL; geom->colortip = NULL; geom->radiusroot = NULL; geom->radiustip = NULL; geom->spec = NULL; geom->opacity = NULL; geom->ambdiff = NULL; geom->gloss = NULL; geom->index = NULL; geom->alpha = NULL; //was missing // geom->spec_tint = NULL; // geom->spec_tint2 = NULL; } int SHAVEalloc_hairtype( HAIRTYPE * geom ) { int x; int ok = 1; int tv, tfv, tf; tv = geom->totalverts + 100; tfv = geom->totalfverts +100; tf = geom->totalfaces + 100; //geom->v=(VERT *) malloc (geom->totalverts*sizeof(VERT)); if( tv > 0 ) { geom->alpha = ( float * ) malloc( tv * sizeof( float ) ); #ifdef _WIN32 assert(_CrtCheckMemory()); #endif if( geom->alpha ) geom->velocity = ( VERT * ) malloc( tv * sizeof( VERT ) ); if( geom->velocity ) geom->ambdiff = ( float * ) malloc( tf * sizeof( float ) ); if( geom->ambdiff ) geom->spec = ( float * ) malloc( tf * sizeof( float ) ); if( geom->spec ) geom->gloss = ( float * ) malloc( tf * sizeof( float ) ); if( geom->gloss ) geom->opacity = ( float * ) malloc( tf * sizeof( float ) ); if( geom->opacity ) geom->colorroot = ( VERT * ) malloc( tf * sizeof( VERT ) ); if( geom->colorroot ) geom->colortip = ( VERT * ) malloc( tf * sizeof( VERT ) ); if( geom->colortip ) geom->radiusroot = ( float * ) malloc( tf * sizeof( float ) ); if( geom->radiusroot ) geom->radiustip = ( float * ) malloc( tf * sizeof( float ) ); if( geom->radiustip ) geom->face_start = ( int * ) malloc( tf * sizeof( int ) ); if( geom->face_start ) geom->face_end = ( int * ) malloc( tf * sizeof( int ) ); if( geom->face_end ) geom->facelist = ( int * ) malloc( tfv * sizeof( int ) ); if( geom->facelist ) geom->index = (int * ) malloc (tf * sizeof (int)); // geom->spec_tint = (VERT * ) malloc (tf * sizeof (VERT)); // geom->spec_tint2 = (VERT * ) malloc (tf * sizeof (VERT)); if( geom->index) geom->uvw = ( VERT * ) malloc( tfv * sizeof( VERT ) ); if( geom->uvw ) geom->uvw2 = ( VERT * ) malloc( tfv * sizeof( VERT ) ); if( geom->uvw2 ) geom->surfNorm = ( VERT * ) malloc( tv * sizeof( VERT ) ); if( geom->surfNorm ) geom->v = ( VERT * ) malloc( tv * sizeof( VERT ) ); } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif if( geom->v != NULL ) for( x = 0; x < geom->totalverts; x++ ) { VERT zero; zero.x = 0.0f; zero.y = 0.0f; zero.z = 0.0f; geom->v[x] = zero; geom->velocity[x] = zero; geom->surfNorm[x] = zero; geom->alpha[x]=0.0f; } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif if( geom->v != NULL ) for( x = 0; x < tfv; x++ ) { VERT zero; zero.x = 0.0f; zero.y = 0.0f; zero.z = 0.0f; geom->facelist[x] = 0; geom->uvw[x] = zero; geom->uvw2[x] = zero; } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif if( geom->v != NULL ) for( x = 0; x < tf; x++ ) { VERT zero; zero.x = 0.0f; zero.y = 0.0f; zero.z = 0.0f; geom->opacity[x] = 0; geom->radiusroot[x] = 0; geom->radiustip[x] = 0; geom->gloss[x] = 0.0f; geom->spec[x] = 0.0f; geom->opacity[x] = 0.0f; geom->colorroot[x] = zero; geom->colortip[x] = zero; geom->face_start[x] = 0; geom->face_end[x] = 0; geom->index[x]=0; } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif if( geom->v == NULL ) { Glow_mem = 1; DRAW_STATUS( "*** ERROR *** Out of memory allocating some geometry" ); //printf ("ran out of memory allocating some geometry .. \n"); // fflush(stdout); SHAVEfree_hairtype( geom ); SHAVEinit_hairtype( geom ); ok = 0; } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif return ( ok ); } void SHAVEfree_hairtype( HAIRTYPE * geom ) { // int x; // int y; //if (geom->totalverts>0) { free( geom->velocity ); free( geom->ambdiff ); free( geom->spec ); free( geom->gloss ); free( geom->opacity ); free( geom->colorroot ); free( geom->colortip ); free( geom->radiusroot ); free( geom->radiustip ); free( geom->face_start ); free( geom->face_end ); free( geom->facelist ); free( geom->v ); free( geom->uvw ); free( geom->uvw2 ); free( geom->surfNorm ); free( geom->index); free( geom->alpha); //was missing // free( geom->spec_tint ); // free( geom->spec_tint2 ); } geom->totalverts = 0; geom->totalfaces = 0; geom->totalfverts = 0; SHAVEinit_hairtype( geom ); } int SHAVEexport_hairtype( HAIRTYPE * ht ) { int x, xx; int yy, zz; int tverts = 0; int tfverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok; HAIRTYPE *outhair; int y; #ifdef _WIN32 assert(_CrtCheckMemory()); #endif SHAVEfree_hairtype( ht ); outhair = ht; for( xx = 0; xx < totalhairfiles; xx++ ) { fetch_hair( xx, 0.0 ); //init_clumping(); init_noise( ); // fprintf (stdout,"SHAVEID = %d LOCAL_CNT = %d\n",(int)SHAVEID,LOCAL_CNT[0]);fflush(stdout); if (freeze.totalverts==0) for( yy = 0; yy < 5; yy++ ) if( LOCAL_CNT[yy] > 0 ) { int next=0; if (sliders[25][yy].value>0.0f) next=LOCAL_PASSES[yy]*(LOCAL_CNT[yy]+1)*(int)(sliders[25][yy].value); else next=LOCAL_PASSES[yy]*(LOCAL_CNT[yy]+1); tfaces+=next; tverts+=next*(LOCAL_SEGS[yy]+3); tfverts+=next*(LOCAL_SEGS[yy]+3); } //free_clumping(); } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif // { // FILE *fp; // fp=fopen("c:\\test.txt","w"); //fprintf(fp,"faces = %d verts = %d\n",tfaces,tverts); // fclose(fp); // } // { // FILE *fp; // fp=fopen("c:\\test.txt","a"); //fprintf(fp,"allocating\n"); // fclose(fp); // } SHAVEfree_hairtype( outhair ); #ifdef _WIN32 assert(_CrtCheckMemory()); #endif outhair->totalverts = tverts + 100; outhair->totalfverts = tfverts + 100; outhair->totalfaces = tfaces + 100; ok = SHAVEalloc_hairtype( outhair ); #ifdef _WIN32 assert(_CrtCheckMemory()); #endif if( ok == 0 ) SHAVEfree_hairtype( outhair ); if( ok == 0 ) if( GLOBAL_VERBOSE ) printf( "couldn't allocate enough memory for export - ABORTED\n" ); outhair->totalverts = 0; outhair->totalfverts = 0; outhair->totalfaces = 0; // { // FILE *fp; // fp=fopen("c:\\test.txt","a"); //fprintf(fp,"allocated\n",tfaces,tverts); // fclose(fp); // } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif if( ok ) for( xx = 0; xx < totalhairfiles; xx++ ) { CURVEINFO ci; WFTYPE wf; int *list; int list_total=0; list=(int *) malloc (tfaces*sizeof(int)); init_geomWF( &wf ); fetch_hair( xx, 0.0 ); init_clumping(); // refreshing the clumping - not sure we need to do this every frame for( yy = 0; yy < 5; yy++ ) { if( LOCAL_CNT[yy] > 0 ) for( zz = 0; zz < LOCAL_CNT[yy]*LOCAL_PASSES[yy]; zz++ ) { list[zz]=zz; list_total++; } if( LOCAL_CNT[yy] > 0 ) { MTbunch_of_hairs(list_total,list,yy,0,&wf,&ci); // if( ci.killme == 0 ) for( x = 0; x < wf.totalfaces; x++ ) { // outhair->surfNorm[tf] = ci.norm; outhair->face_start[tf] = tfv+wf.face_start[x]; outhair->face_end[tf] = tfv+wf.face_end[x]; outhair->radiusroot[tf] = wf.r1[x]; outhair->radiustip[tf] = wf.r2[x]; // fprintf (stdout,"r1 = %f r2 = %f\n",wf.r1[x],wf.r2[x]);fflush(stdout); outhair->colorroot[tf] = wf.color[wf.face_start[x]]; outhair->colortip[tf] = wf.color[wf.face_end[x] - 1]; outhair->spec[tf] = sliders[4][yy].value; // speccorlor outhair->gloss[tf] = sliders[5][yy].value; outhair->ambdiff[tf] = sliders[6][yy].value; if( LOCAL_PASSES[yy] > 0 ) outhair->opacity[tf] = ( 1.0f / ( float ) LOCAL_PASSES[yy] ); else outhair->opacity[tf] = 0.0f; if( outhair->opacity[tf] > 1.0f ) outhair->opacity[tf] = 1.0f; if( outhair->opacity[tf] < 0.0f ) outhair->opacity[tf] = 0.0f; tf++; outhair->totalfaces++; } tfv=outhair->totalfverts; for( y = 0; y < wf.totalfverts; y++ ) { int g; float rad; float interp; outhair->facelist[outhair->totalfverts] = wf.facelist[y]+tfv; outhair->totalfverts++; } tfv=outhair->totalfverts; for( y = 0; y < wf.totalverts; y++ ) { outhair->surfNorm[outhair->totalverts] = wf.vn[y]; outhair->v[outhair->totalverts] = wf.v[y]; outhair->uvw[outhair->totalverts] = wf.uv[y]; outhair->velocity[outhair->totalverts] = wf.velocity[y]; tv++; outhair->totalverts++; } } free_geomWF( &wf ); } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif free_clumping(); } #ifdef _WIN32 assert(_CrtCheckMemory()); #endif return ( ok ); } int SHAVEexport_instances( WFTYPE * ht ) { int x, xx; int yy, zz; int tverts = 0; int tfverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok=1; WFTYPE *outhair; int y; free_geomWF( ht ); outhair = ht; for( xx = 0; xx < totalhairfiles; xx++ ) { fetch_hair( xx, 0.0 ); init_clumping(); init_noise( ); // fprintf (stdout,"SHAVEID = %d LOCAL_CNT = %d\n",(int)SHAVEID,LOCAL_CNT[0]);fflush(stdout); if (freeze.totalverts==0) for( yy = 0; yy < 5; yy++ ) if( LOCAL_CNT[yy] > 0 ) { int next=0; if (sliders[25][yy].value>0.0f) next=LOCAL_PASSES[yy]*(LOCAL_CNT[yy]+1)*(int)(sliders[25][yy].value); else next=LOCAL_PASSES[yy]*(LOCAL_CNT[yy]+1); tfaces+=next; tverts+=next*(LOCAL_SEGS[yy]+3); tfverts+=next*(LOCAL_SEGS[yy]+3); } } // { // FILE *fp; // fp=fopen("c:\\test.txt","w"); //fprintf(fp,"faces = %d verts = %d\n",tfaces,tverts); // fclose(fp); // } // { // FILE *fp; // fp=fopen("c:\\test.txt","a"); //fprintf(fp,"allocating\n"); // fclose(fp); // } free_geomWF( outhair ); outhair->totalverts = tverts + 100; outhair->totalfverts = tfverts + 100; outhair->totalfaces = tfaces + 100; alloc_geomWF( outhair ); outhair->totalverts = 0; outhair->totalfverts = 0; outhair->totalfaces = 0; // { // FILE *fp; // fp=fopen("c:\\test.txt","a"); //fprintf(fp,"allocated\n",tfaces,tverts); // fclose(fp); // } for( xx = 0; xx < totalhairfiles; xx++ ) { CURVEINFO ci; WFTYPE wf; int *list; int list_total=0; list=(int *) malloc (tfaces*sizeof(int)); init_geomWF( &wf ); fetch_hair( xx, 0.0 ); init_clumping(); // refreshing the clumping - not sure we need to do this every frame for( yy = 0; yy < 5; yy++ ) { if( LOCAL_CNT[yy] > 0 ) for( zz = 0; zz < LOCAL_CNT[yy]*LOCAL_PASSES[yy]; zz++ ) { list[zz]=zz; list_total++; } if( LOCAL_CNT[yy] > 0 ) { int tf=0,tfv=0,tv=0; MTbunch_of_hairs(list_total,list,yy,0,&wf,&ci); // if( ci.killme == 0 ) for( x = 0; x < wf.totalfaces; x++ ) { // outhair->surfNorm[tf] = ci.norm; outhair->face_start[tf] = tfv+wf.face_start[x]; outhair->face_end[tf] = tfv+wf.face_end[x]; // outhair->radiusroot[tf] = wf.r1[x]; // outhair->radiustip[tf] = wf.r2[x]; // fprintf (stdout,"r1 = %f r2 = %f\n",wf.r1[x],wf.r2[x]);fflush(stdout); tf++; outhair->totalfaces++; } tfv=outhair->totalfverts; for( y = 0; y < wf.totalfverts; y++ ) { int g; float rad; float interp; outhair->facelist[outhair->totalfverts] = wf.facelist[y]+tfv; outhair->totalfverts++; } tfv=outhair->totalfverts; for( y = 0; y < wf.totalverts; y++ ) { outhair->vn[outhair->totalverts] = wf.vn[y]; outhair->v[outhair->totalverts] = wf.v[y]; outhair->color[outhair->totalverts] = wf.color[y]; outhair->uv[outhair->totalverts] = wf.uv[y]; outhair->velocity[outhair->totalverts] = wf.velocity[y]; tv++; outhair->totalverts++; } } free_geomWF( &wf ); } } return ( ok ); } typedef struct { int totalfaces, totalverts, totalfverts; int totalfaces2; } VOXCOUNT; void expand_bound(VERT *b1, VERT *b2,float perc) { float largest=0; VERT diff; diff.x=b2->x-b1->x; diff.y=b2->y-b1->y; diff.z=b2->z-b1->z; b1->x+=diff.x/2.0f; b1->y+=diff.y/2.0f; b1->z+=diff.z/2.0f; largest=fabs(diff.x); if (fabs(diff.y)>largest) largest=fabs(diff.y); if (fabs(diff.z)>largest) largest=fabs(diff.z); if (fabs(diff.x)x-=diff.x/2.0f; b1->y-=diff.y/2.0f; b1->z-=diff.z/2.0f; b2->x=b1->x+diff.x; b2->y=b1->y+diff.y; b2->z=b1->z+diff.z; } SHAVE_RENDER_HOST Grender_host=kShaveHostMR; void SHAVEset_render_host(SHAVE_RENDER_HOST type) { Grender_host=type; } static int init_hairstack_from_archive_common( void *indata ) // returning the vox res { int y; void *fp = NULL; int ret = 0; unsigned char fileversion = 'a'; unsigned char softwareversion = 'a'; SHAVEclear_stack( ); //Global_debug=fopen("c:\\renderlog.txt","w"); // printf ("debug1\n");fflush(stdout); // SHAVEinit( ); // printf ("debug2\n");fflush(stdout); if( Global_debug ) fprintf( Global_debug, "SHAVEinit_hairstack_from_archive\n" ); // printf ("debug3\n");fflush(stdout); SHAVEclear_stack( ); fp = MYfopen( indata, "r+b" ); // fp = fopen( indata, "r+b" ); if( !fp ) ret = -1; // printf ("debug4\n");fflush(stdout); if( fp ) { int i; int x; char c; unsigned int current_pos = 0; unsigned int ii; // current_pos=(unsigned int)ftell(fp); MYfseek( fp, 0, SEEK_SET ); MYfread( &fileversion, 1, 1, fp ); // fileversion MYfread( &softwareversion, 1, 1, fp ); // fileversion MYfread( &ret, 4, 1, fp ); // vox res ret = ( int ) ret; ii = ret; Gvoxdim = ret; // printf ("debug5\n");fflush(stdout); MYfseek( fp, 5 + 1, SEEK_SET ); MYfread( ¤t_pos, 4, 1, fp ); // position of the hairstack MYfseek( fp, current_pos, SEEK_SET ); MYfread( &totalhairfiles, 4, 1, fp ); for( x = 0; x < totalhairfiles; x++ ) { unsigned int i; int f; int qq; MYfread( &i, 4, 1, fp ); hairfiles[x].ID = i; MYfread( &i, 4, 1, fp ); hairfiles[x].size = i; MYfread( &f, 4, 1, fp ); hairfiles[x].time = f; hairstate[x].time = f; alloc_MEMFILE( &hairfiles[x] ); for( qq = 0; qq < hairfiles[x].size; qq++ ) { MYfread( &hairfiles[x].data[qq], 1, 1, fp ); } MYfread( &i, 4, 1, fp ); hairstate[x].ID = i; MYfread( &i, 4, 1, fp ); hairstate[x].size = i; MYfread( &f, 4, 1, fp ); hairstate[x].time = f; alloc_MEMFILE( &hairstate[x] ); for( qq = 0; qq < hairstate[x].size; qq++ ) { MYfread( &hairstate[x].data[qq], 1, 1, fp ); } { SHAVEPARMS *sp; sp = &Gshavep[x]; for( qq = 0; qq < 5; qq++ ) { MYfread( &sp->haircount[qq], 4, 1, fp ); } if( fileversion >= 'c' ) for( qq = 0; qq < 5; qq++ ) { MYfread( &sp->shadowHaircount[qq], 4, 1, fp ); } for( qq = 0; qq < 5; qq++ ) { MYfread( &sp->passes[qq], 4, 1, fp ); } for( qq = 0; qq < 5; qq++ ) { int aa; for( aa = 0; aa < 60; aa++ ) { MYfread( &sp->slider_val[aa][qq], 4, 1, fp ); } } for( qq = 0; qq < 5; qq++ ) { int aa, lb; for( aa = 0; aa < 60; aa++ ) { for( lb = 0; lb < 50; lb++ ) MYfread( &sp->slider_lable[aa][qq][lb], 1, 1, fp ); } } for( qq = 0; qq < 5; qq++ ) { int aa; for( aa = 0; aa < 60; aa++ ) { MYfread( &sp->painted[aa][qq], 4, 1, fp ); } } MYfread( &sp->total_guides, 4, 1, fp ); MYfread( &sp->instancing_status, 4, 1, fp ); for( qq = 0; qq < 5; qq++ ) { MYfread( &sp->collide[qq], 4, 1, fp ); } MYfread( &sp->collision_method, 4, 1, fp ); for( qq = 0; qq < 5; qq++ ) { MYfread( &sp->frizz_anim_dir[qq].x, 4, 1, fp ); MYfread( &sp->frizz_anim_dir[qq].y, 4, 1, fp ); MYfread( &sp->frizz_anim_dir[qq].z, 4, 1, fp ); } for( qq = 0; qq < 5; qq++ ) { MYfread( &sp->segs[qq], 4, 1, fp ); } MYfread( &sp->dontinterpolate, 4, 1, fp ); MYfread( &sp->geom_shadow, 4, 1, fp ); for( qq = 0; qq < 60; qq++ ) MYfread( &sp->uv_link[qq], 4, 1, fp ); // fileversion d if( fileversion >= 'd' ) for( qq = 0; qq < 64; qq++ ) MYfread( &sp->name[qq], 1, 1, fp ); // fileversion g // spec_tint if( fileversion >= 'g' ) { MYfread( &sp->spec_tint.x, 4, 1, fp ); MYfread( &sp->spec_tint.y, 4, 1, fp ); MYfread( &sp->spec_tint.z, 4, 1, fp ); } if( fileversion >= 'h' ) { MYfread( &sp->squirrel, 4, 1, fp ); MYfread( &sp->flyaway_percent, 4, 1, fp ); MYfread( &sp->clumps, 4, 1, fp ); } // spec fix // fileversion h // if( fileversion >= 'h' ) // read in use_old_splayscale // MYfread( &sp->use_old_splayscale, 4, 1, fp ); { int tmpi; if( fileversion >= 'i' ) // read in use_old_splayscale MYfread( &tmpi, 4, 1, fp ); sp->rand_seed_offset=tmpi; Grandom_seed_offset=(unsigned long)sp->rand_seed_offset; if( fileversion >= 'j' ) { MYfread( &sp->spec_tint2.x, 4, 1, fp ); MYfread( &sp->spec_tint2.y, 4, 1, fp ); MYfread( &sp->spec_tint2.z, 4, 1, fp ); } } } fetch_hair(x,0.0f); //SHAVEID=x; //init_clumping(); } for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) { MYfread( &LWCamOPEN.view[x][y], 4, 1, fp ); } for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfread( &LWCamOPEN.iview[x][y], 4, 1, fp ); MYfread( &LWCamOPEN.nearclip, 4, 1, fp ); MYfread( &LWCamOPEN.wind, 4, 1, fp ); MYfread( &LWCamOPEN.xlight, 4, 1, fp ); MYfread( &LWCamOPEN.shadsamps, 4, 1, fp ); MYfread( &LWCamOPEN.shadowcolor.x, 4, 1, fp ); MYfread( &LWCamOPEN.shadowcolor.y, 4, 1, fp ); MYfread( &LWCamOPEN.shadowcolor.z, 4, 1, fp ); MYfread( &LWCamOPEN.aspect, 4, 1, fp ); MYfread( &LWCamOPEN.id, 4, 1, fp ); MYfread( &LWCamOPEN.wpos.x, 4, 1, fp ); MYfread( &LWCamOPEN.wpos.y, 4, 1, fp ); MYfread( &LWCamOPEN.wpos.z, 4, 1, fp ); MYfread( &LWCamOPEN.fuzz, 4, 1, fp ); MYfread( &LWCamOPEN.xlight, 4, 1, fp ); MYfread( &LWCamOPEN.xres, 4, 1, fp ); MYfread( &LWCamOPEN.yres, 4, 1, fp ); MYfread( &LWCamOPEN.zoom, 4, 1, fp ); LWCamOPEN.Gzbuff = NULL; LWCamOPEN.zbuff = NULL; LWCamOPEN.ibuff = NULL; LWCamOPEN.lumbuff = NULL; LWCamOPEN.geombuff = NULL; LWCamOPEN.caustics = 0; LWCamOPEN.wind = 0; LWCamOPEN.radiosity = 0; LWcam.zbuff = NULL; LWcam.Gzbuff = NULL; LWcam.geombuff = NULL; LWcam.ibuff = NULL; for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) { MYfread( &LWCamCLOSE.view[x][y], 4, 1, fp ); // printf ("%f ",LWCamCLOSE.view[x][y]); } //printf ("end inbound matrix\n"); for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) { MYfread( &LWCamCLOSE.iview[x][y], 4, 1, fp ); } MYfread( &LWCamCLOSE.nearclip, 4, 1, fp ); MYfread( &LWCamCLOSE.wind, 4, 1, fp ); MYfread( &LWCamCLOSE.xlight, 4, 1, fp ); MYfread( &LWCamCLOSE.shadsamps, 4, 1, fp ); MYfread( &LWCamCLOSE.shadowcolor.x, 4, 1, fp ); MYfread( &LWCamCLOSE.shadowcolor.y, 4, 1, fp ); MYfread( &LWCamCLOSE.shadowcolor.z, 4, 1, fp ); MYfread( &LWCamCLOSE.aspect, 4, 1, fp ); MYfread( &LWCamCLOSE.id, 4, 1, fp ); MYfread( &LWCamCLOSE.wpos.x, 4, 1, fp ); MYfread( &LWCamCLOSE.wpos.y, 4, 1, fp ); MYfread( &LWCamCLOSE.wpos.z, 4, 1, fp ); MYfread( &LWCamCLOSE.fuzz, 4, 1, fp ); MYfread( &LWCamCLOSE.xlight, 4, 1, fp ); MYfread( &LWCamCLOSE.xres, 4, 1, fp ); MYfread( &LWCamCLOSE.yres, 4, 1, fp ); MYfread( &LWCamCLOSE.zoom, 4, 1, fp ); LWCamCLOSE.Gzbuff = NULL; LWCamCLOSE.zbuff = NULL; LWCamCLOSE.ibuff = NULL; LWCamCLOSE.lumbuff = NULL; LWCamCLOSE.geombuff = NULL; memcpy( LWcam.view, LWCamOPEN.view, sizeof( LWCamOPEN.view ) ); memcpy( LWcam.iview, LWCamOPEN.iview, sizeof( LWCamOPEN.iview ) ); { int maxp = 0; 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; } MYfread( &totallights, 4, 1, fp ); { int l; init_noise( ); srand( 0 ); Jsrand( 0 ); // for( x = 0; x < 255; x++ ) // { // LWlight[x].ibuff = NULL; // LWlight[x].zbuff = NULL; // LWlight[x].Gzbuff = NULL; // LWlight[x].lumbuff = NULL; // LWlight[x].geombuff = NULL; // } for( l = 0; l < totallights; l++ ) { for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfread( &LWlight[l].view[x][y], 4, 1, fp ); for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfread( &LWlight[l].iview[x][y], 4, 1, fp ); MYfread( &LWlight[l].nearclip, 4, 1, fp ); MYfread( &LWlight[l].wind, 4, 1, fp ); MYfread( &LWlight[l].xlight, 4, 1, fp ); MYfread( &LWlight[l].shadsamps, 4, 1, fp ); MYfread( &LWlight[l].shadowcolor.x, 4, 1, fp ); MYfread( &LWlight[l].shadowcolor.y, 4, 1, fp ); MYfread( &LWlight[l].shadowcolor.z, 4, 1, fp ); MYfread( &LWlight[l].color.x, 4, 1, fp ); MYfread( &LWlight[l].color.y, 4, 1, fp ); MYfread( &LWlight[l].color.z, 4, 1, fp ); MYfread( &LWlight[l].aspect, 4, 1, fp ); MYfread( &LWlight[l].id, 4, 1, fp ); MYfread( &LWlight[l].wpos.x, 4, 1, fp ); MYfread( &LWlight[l].wpos.y, 4, 1, fp ); MYfread( &LWlight[l].wpos.z, 4, 1, fp ); MYfread( &LWlight[l].fuzz, 4, 1, fp ); MYfread( &LWlight[l].xlight, 4, 1, fp ); MYfread( &LWlight[l].xres, 4, 1, fp ); LWlight[l].xrsq = LWlight[l].xres * LWlight[l].xres; MYfread( &LWlight[l].yres, 4, 1, fp ); MYfread( &LWlight[l].zoom, 4, 1, fp ); // LWlight[l].Gzbuff = NULL; // LWlight[l].zbuff = NULL; // LWlight[l].ibuff = NULL; // LWlight[l].lumbuff = NULL; } } LWCamCLOSE.xres = LWCamOPEN.xres; LWCamCLOSE.yres = LWCamOPEN.yres; LWCamCLOSE.aspect = LWCamOPEN.aspect; LWCamCLOSE.caustics = 0; LWCamCLOSE.radiosity = 0; LWCamCLOSE.wind = 0; LWcam.geombuff = NULL; LWcam.ibuff = NULL; LWcam.zbuff = NULL; LWcam.Gzbuff = NULL; LWcam.xres = ( int ) LWCamOPEN.xres; LWcam.yres = ( int ) LWCamOPEN.yres; LWcam.aspect = ( float ) LWCamOPEN.aspect; LWcam.nearclip = LWCamOPEN.nearclip; // now we want to read the texture cache { int x; for( x = 0; x < totalhairfiles; x++ ) { for( y = 0; y < 5; y++ ) { MYfread( &Gtex_totalchannels[x][y], 4, 1, fp ); } } for( y = 0; y < 60; y++ ) { for( x = 0; x < totalhairfiles; x++ ) { MYfread( &Gtex_channellink[x][y], 4, 1, fp ); } } for( x = 0; x < totalhairfiles; x++ ) // ok we're going to allocate the texture cache tables for( y = 0; y < 5; y++ ) { int t; // t = Gtex_totalchannels[x][y] * Gshavep[x].haircount[y] * Gshavep[x].passes[y]; t = Gtex_totalchannels[x][y] * Gshavep[x].haircount[y] * Gshavep[x].passes[y]; //printf ("t = %d\n",t); // if (t!=0) t += 40; // fprintf (stdout,"node %d slg %d chans %d haircount %d passes %d\n",x,y,Gtex_totalchannels[x][y],Gshavep[x].haircount[y],Gshavep[x].passes[y]);fflush(stdout); Gtex_cacheinfo[x][y] = ( float * ) malloc( t * sizeof( float ) ); t = Gshavep[x].haircount[y]* Gshavep[x].passes[y];// * Gshavep[x].passes[y]; t += 40; //printf ("t = %d\n",t); // if (t!=0) Gtex_cachedisplace[x][y] = ( VERT * ) malloc( t * sizeof( VERT ) ); } for( x = 0; x < totalhairfiles; x++ ) for( y = 0; y < 5; y++ ) { int t; int z; t = Gtex_totalchannels[x][y] * Gshavep[x].passes[y] * Gshavep[x].haircount[y]; // t = Gtex_totalchannels[x][y] * Gshavep[x].haircount[y]; for( z = 0; z < t; z++ ) { MYfread( &Gtex_cacheinfo[x][y][z], 4, 1, fp ); } t = Gshavep[x].passes[y] * Gshavep[x].haircount[y]; // t = Gshavep[x].haircount[y]; for( z = 0; z < t; z++ ) { Gtex_cachedisplace[x][y][z].x = 0.0f; Gtex_cachedisplace[x][y][z].y = 0.0f; Gtex_cachedisplace[x][y][z].z = 0.0f; if( fileversion < 'e' ) MYfread( &Gtex_cachedisplace[x][y][z], 4, 1, fp ); if( fileversion >= 'f' ) { MYfread( &Gtex_cachedisplace[x][y][z].x, 4, 1, fp ); MYfread( &Gtex_cachedisplace[x][y][z].y, 4, 1, fp ); MYfread( &Gtex_cachedisplace[x][y][z].z, 4, 1, fp ); } } } TEXCACHEMODE = 1; } // now, we want to write out the occlusion mesh { int x; int zr = 0; int tv, tfv, tf; MYfread( &tv, 4, 1, fp ); MYfread( &tfv, 4, 1, fp ); MYfread( &tf, 4, 1, fp ); MYfread( &zr, 4, 1, fp ); // leave room for some more params MYfread( &zr, 4, 1, fp ); if( tv > 0 ) { GLOBALocclude = ( WFTYPE * ) malloc( sizeof( WFTYPE ) ); init_geomWF( GLOBALocclude ); GLOBALocclude->totalverts = tv; GLOBALocclude->totalfverts = tfv; GLOBALocclude->totalfaces = tf; alloc_geomWF( GLOBALocclude ); for( x = 0; x < GLOBALocclude->totalverts; x++ ) { MYfread( &GLOBALocclude->v[x].x, 4, 1, fp ); MYfread( &GLOBALocclude->v[x].y, 4, 1, fp ); MYfread( &GLOBALocclude->v[x].z, 4, 1, fp ); MYfread( &GLOBALocclude->velocity[x].x, 4, 1, fp ); MYfread( &GLOBALocclude->velocity[x].y, 4, 1, fp ); MYfread( &GLOBALocclude->velocity[x].z, 4, 1, fp ); //MYfread(&GLOBALocclude->uv[x].x,4,1,fp); // this should really be per-fvert //MYfread(&GLOBALocclude->uv[x].y,4,1,fp); //MYfread(&GLOBALocclude->uv[x].z,4,1,fp); } for( x = 0; x < GLOBALocclude->totalfverts; x++ ) { MYfread( &GLOBALocclude->facelist[x], 4, 1, fp ); } for( x = 0; x < GLOBALocclude->totalfaces; x++ ) { MYfread( &GLOBALocclude->face_start[x], 4, 1, fp ); MYfread( &GLOBALocclude->face_end[x], 4, 1, fp ); } } } // done stack_is_from_archive = 1; // SHAVEID = -1; MYfclose( fp ); } if( Global_debug ) { int xx; fprintf( Global_debug, "Some Stats:\n" ); fprintf( Global_debug, "totallights = %d\n", totallights ); fprintf( Global_debug, "totalnodes = %d\n", totalhairfiles ); for( xx = 0; xx < totallights; xx++ ) { fprintf( Global_debug, "LWlight[%d].xres = %d | position = %f %f %f | zoom %f\n", xx, LWlight[xx].xres, LWlight[xx].wpos.x, LWlight[xx].wpos.y, LWlight[xx].wpos.z, LWlight[xx].zoom ); } } //for (x=0;x zvox ) x = zvox; if( x < 0 ) x = 0; MYfseek( fp, x * 4 * 2 + 9 + 1, SEEK_SET ); { t = 0; MYfread( &t, 4, 1, fp ); // high order - placeholders for the file pos addresses MYfread( &t, 4, 1, fp ); // low order //printf ("debug4\n");fflush(stdout); pos_lookup = ( int ) t; // printf ("pos_lookup = %d\n",pos_lookup); } // for (x=0;x<20*20*20;x++) { int a; unsigned int b; int bb; int tfv = 0; tf = 0, tv = 0; current_pos = pos_lookup; MYfseek( fp, current_pos, SEEK_SET ); //printf ("debug5\n");fflush(stdout); bb = 0; MYfread( &bb, 4, 1, fp ); // total_faces placeholder ev.totalfaces = ( int ) bb; //printf ("%d position[%d]= %d hairs in this voxel = %d \n",x*4*2+9+1,x,current_pos,bb); MYfread( &obound1->x, 4, 1, fp ); // this is the bounding box of the voxel MYfread( &obound1->y, 4, 1, fp ); MYfread( &obound1->z, 4, 1, fp ); MYfread( &obound2->x, 4, 1, fp ); MYfread( &obound2->y, 4, 1, fp ); MYfread( &obound2->z, 4, 1, fp ); //printf ("bounds %f %f %f : %f %f %f\n", // obound1->x,obound1->y,obound1->z, // obound2->x,obound2->y,obound2->z); //printf ("debug6\n");fflush(stdout); } } MYfclose( fp ); if( obound1->x > obound2->x ) ret = 0; return ( ret ); } int SHAVEimport_archive_voxel_bbox( CHNG *fname, int xxx, int yyy, int zzz, VERT * obound1, VERT * obound2 ) { RW_CONTEXT = RW_DISK; return import_archive_voxel_bbox_common( fname, xxx, yyy, zzz, obound1, obound2 ); } int SHAVEimport_mem_archive_voxel_bbox( MEMFILE * mem, int xxx, int yyy, int zzz, VERT * obound1, VERT * obound2 ) { RW_CONTEXT = RW_LOCAL; return import_archive_voxel_bbox_common( mem, xxx, yyy, zzz, obound1, obound2 ); } int most_diff=0; // this is just for diagnostics static void import_archive_voxel_common( void *indata, int xxx, int yyy, int zzz, HAIRTYPE * outhair, int isShadow ) { void *fp = NULL; int x; int tverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok; VERT rbound1, rbound2; int y; unsigned int pos_lookup; int voxres; VERT obound1, obound2; VOXCOUNT ev; int *hind = NULL, *pind = NULL, *nind = NULL, *slgind = NULL; SHAVEinit_hairtype( outhair ); SHAVEfree_hairtype( outhair ); #ifdef DOUNICODE fp = (FILE *) MYfopen( indata, L"r+b" ); #else fp = (FILE *) MYfopen( indata, "r+b" ); #endif if( fp ) { int tverts = 0, tfverts = 0, tfaces = 0; unsigned int t; unsigned char fileversion = 'a'; unsigned char softwareversion = 'a'; unsigned int current_pos; int zvox; MYfread( &fileversion, 1, 1, fp ); MYfread( &softwareversion, 1, 1, fp ); MYfread( &t, 4, 1, fp ); // vox table dimensions voxres = t; zvox=(voxres-1)+(voxres-1)*voxres+(voxres-1)*voxres*voxres; printf ("voxres = %d voxel %d %d %d\n",voxres,xxx,yyy,zzz); MYfread( &t, 4, 1, fp ); // stackfileposition x = xxx + yyy * voxres + zzz * voxres * voxres; if( x < 0 ) x = 0; if( x > zvox ) x = zvox; MYfseek( fp, x * 4 * 2 + 9 + 1, SEEK_SET ); { t = 0; MYfread( &t, 4, 1, fp ); // high order - placeholders for the file pos addresses pos_lookup = ( int ) t; MYfread( &t, 4, 1, fp ); // low order // pos_lookup=(int)t; // printf ("pos_lookup = %d\n",pos_lookup); } // for (x=0;x<20*20*20;x++) { int a; unsigned int b; int bb; int tfv = 0; tf = 0, tv = 0; current_pos = pos_lookup; MYfseek( fp, current_pos, SEEK_SET ); bb = 0; MYfread( &bb, 4, 1, fp ); // total_faces placeholder ev.totalfaces2 = ( int ) bb; //printf ("in totalfaces2 = %d\n",bb); MYfread( &obound1.x, 4, 1, fp ); // this is the bounding box of the voxel MYfread( &obound1.y, 4, 1, fp ); MYfread( &obound1.z, 4, 1, fp ); MYfread( &obound2.x, 4, 1, fp ); MYfread( &obound2.y, 4, 1, fp ); MYfread( &obound2.z, 4, 1, fp ); MYfread( &tfaces, 4, 1, fp ); MYfread( &tfverts, 4, 1, fp ); MYfread( &tverts, 4, 1, fp ); // MYfread(&tfaces,4,1,fp); // fprintf (stdout, "bb = %d totalface = %d totalverts = %d totalfverts = %d\n",bb,tfaces,tverts,tfverts);fflush(stdout); a = ev.totalfaces2; a += 40; hind = ( int * ) malloc( a * sizeof( int ) ); nind = ( int * ) malloc( a * sizeof( int ) ); pind = ( int * ) malloc( a * sizeof( int ) ); slgind = ( int * ) malloc( a * sizeof( int ) ); { outhair->totalfaces = tfaces ; outhair->totalfverts = tfverts; outhair->totalverts = tverts; } //printf ("tverts = %d\n",tverts); if (tverts>0) SHAVEalloc_hairtype( outhair ); outhair->totalfaces = 0; outhair->totalfverts = 0; outhair->totalverts = 0; for( a = 0; a < ev.totalfaces2; a++ ) { hind[a] = 0; nind[a] = 0; pind[a] = 0; slgind[a] = 0; } //if (0==1) if (tverts>0) { int lastn = -1; for( a = 0; a < ev.totalfaces2; a++ ) // all the hairs in this voxel { float tex_lookup[60]; int pp; int totaltex; CURVEINFO ci; WFTYPE wf; init_geomWF( &wf ); TEXCACHEMODE = 1; MYfread( &nind[a], 4, 1, fp ); // here's the info we'll need for a regen MYfread( &pind[a], 4, 1, fp ); MYfread( &hind[a], 4, 1, fp ); MYfread( &slgind[a], 4, 1, fp ); TEXCACHEMODE = 1; if( nind[a] != ( int ) GnodeID ) { fetch_hair( nind[a], 0.0 ); SHAVEID = nind[a]; GnodeID = nind[a]; // init_clumping(); } // Gpass = pind[a]; Gpass=0; if( freeze.totalverts == 0 ) { // if( ( isShadow == 1 ) && ( hind[a] < LOCAL_SHADCNT[slgind[a]] ) ) // SHAVEmake_a_curve( pind[a], slgind[a], hind[a], LOCAL_SEGS[slgind[a]], &wf, &ci ); SHAVEmake_a_curve( 0, slgind[a], hind[a], LOCAL_SEGS[slgind[a]], &wf, &ci ); // if( isShadow == 0 ) // SHAVEmake_a_curve( pind[a], slgind[a], hind[a], LOCAL_SEGS[slgind[a]], &wf, &ci ); } if( freeze.totalverts != 0 ) { if( ( isShadow == 1 ) && ( hind[a] < LOCAL_SHADCNT[slgind[a]] ) ) SHAVEmake_a_hair( 0, slgind[a], hind[a], LOCAL_SEGS[slgind[a]], &wf ); // if( ( isShadow == 1 ) && ( hind[a] < LOCAL_SHADCNT[slgind[a]] ) ) // SHAVEmake_a_hair( pind[a], slgind[a], hind[a], LOCAL_SEGS[slgind[a]], &wf ); // if( isShadow == 0 ) // SHAVEmake_a_hair( pind[a], slgind[a], hind[a], LOCAL_SEGS[slgind[a]], &wf ); if( isShadow == 0 ) SHAVEmake_a_hair( 0, slgind[a], hind[a], LOCAL_SEGS[slgind[a]], &wf ); } // TEXCACHEMODE=0; // printf ("make a curve\n"); //if (0==1) if( freeze.totalverts == 0 ) if( wf.totalverts > 0 ) { int x1, y1, z1; int vstart = 0; int vflstart = 0; int vfstart = 0; vstart = outhair->totalverts; vflstart = outhair->totalfverts; vfstart = outhair->totalfaces; for( x1 = 0; x1 < wf.totalverts; x1++ ) { outhair->v[outhair->totalverts] = wf.v[x1]; outhair->velocity[outhair->totalverts] = wf.velocity[x1]; outhair->totalverts++; } for( x1 = 0; x1 < wf.totalfverts; x1++ ) { outhair->facelist[outhair->totalfverts] = wf.facelist[x1] + vflstart; outhair->totalfverts++; } // if (0==1) for( x1 = 0; x1 < wf.totalfaces; x1++ ) { int indd; // [pass][mult][hairID] // outhair->spec_tint[outhair->totalfaces]=ci.spec_tint; // outhair->spec_tint2[outhair->totalfaces]=ci.spec_tint2; outhair->index[outhair->totalfaces]=wf.index[x1]; outhair->surfNorm[outhair->totalfaces] = wf.vn[x1] ; outhair->face_start[outhair->totalfaces] = wf.face_start[x1] + vflstart; outhair->face_end[outhair->totalfaces] = wf.face_end[x1] + vflstart; outhair->colorroot[outhair->totalfaces] = wf.color[wf.facelist[wf.face_start[x1]]]; outhair->colortip[outhair->totalfaces] = wf.color[wf.facelist[wf.face_end[x1] - 1]]; outhair->radiusroot[outhair->totalfaces] = ci.baserad; outhair->radiustip[outhair->totalfaces] = ci.tiprad; // if (0==1) for( y1 = wf.face_start[x1]; y1 < wf.face_end[x1]; y1++ ) { outhair->uvw[outhair->facelist[y1 + vstart]] = wf.uv[wf.facelist[y1]]; outhair->alpha[outhair->facelist[y1 + vstart]] =wf.alpha[wf.facelist[y1]]; } outhair->gloss[outhair->totalfaces] = ci.kspec; outhair->spec[outhair->totalfaces] = ci.spec; outhair->ambdiff[outhair->totalfaces] = ci.diff; if( LOCAL_PASSES[slgind[a]] > 0 ) outhair->opacity[outhair->totalfaces] = 1.0f / ( float ) LOCAL_PASSES[slgind[a]]; outhair->totalfaces++; } } if( freeze.totalverts != 0 ) if( wf.totalverts > 0 ) { int x1, y1, z1; int vstart = 0; int vflstart = 0; int vfstart = 0; vstart = outhair->totalverts; vflstart = outhair->totalfverts; vfstart = outhair->totalfaces; for( x1 = 0; x1 < wf.totalverts; x1++ ) { outhair->v[outhair->totalverts] = wf.v[x1]; outhair->velocity[outhair->totalverts] = wf.velocity[x1]; outhair->surfNorm[outhair->totalverts] = wf.vn[x1]; outhair->totalverts++; } for( x1 = 0; x1 < wf.totalfverts; x1++ ) { outhair->facelist[outhair->totalfverts] = wf.facelist[x1] + vflstart; outhair->totalfverts++; } // if (0==1) for( x1 = 0; x1 < wf.totalfaces; x1++ ) { //s outhair->surfNorm[outhair->totalfaces] = ci.norm; outhair->index[outhair->totalfaces]=wf.index[x1]; outhair->face_start[outhair->totalfaces] = wf.face_start[x1] + vflstart; outhair->face_end[outhair->totalfaces] = wf.face_end[x1] + vflstart; outhair->colorroot[outhair->totalfaces] = wf.color[wf.facelist[wf.face_start[x1]]]; outhair->colortip[outhair->totalfaces] = wf.color[wf.facelist[wf.face_end[x1] - 1]]; outhair->radiusroot[outhair->totalfaces] = ci.baserad; outhair->radiustip[outhair->totalfaces] = ci.tiprad; // if (0==1) for( y1 = wf.face_start[x1]; y1 < wf.face_end[x1]; y1++ ) { outhair->uvw[outhair->facelist[y1 + vstart]] = wf.uv[wf.facelist[y1]]; } outhair->gloss[outhair->totalfaces] = ci.kspec; outhair->spec[outhair->totalfaces] = ci.spec; outhair->ambdiff[outhair->totalfaces] = ci.diff; if( LOCAL_PASSES[slgind[a]] > 0 ) outhair->opacity[outhair->totalfaces] = 1.0f / ( float ) LOCAL_PASSES[slgind[a]]; outhair->totalfaces++; } } // append_hairtype(outhair,&wf,&ci); if (wf.totalverts>0) free_geomWF( &wf ); } } // if (outhair->totalfaces > tfaces) { // fprintf (stdout,"ev.totalfaces2 = %d outhair->totalfaces = %d tfaces = %d difference = %d percentage = %f faces/hairs = %f\n",ev.totalfaces2, outhair->totalfaces,tfaces,outhair->totalfaces-tfaces,(float)(outhair->totalfaces-tfaces)/(float)outhair->totalfaces,(float)outhair->totalfaces/(float)ev.totalfaces2);fflush(stdout); } // if (outhair->totalverts > tverts) { fprintf (stdout,"outhair->totalverts = %d tfaces = %d difference = %d percentage = %f\n",outhair->totalverts,tverts, outhair->totalverts-tverts,(float)(outhair->totalverts-tverts)/(float)outhair->totalverts);fflush(stdout); } //if ((outhair->totalfaces-tfaces)> most_diff) most_diff=(outhair->totalfaces-tfaces); //if (ev.totalfaces) //printf ("the voxel tags were read - %d\n",ev.totalfaces); { if (slgind) free( slgind ); if (nind) free( nind ); if (pind) free( pind ); if (hind) free( hind ); slgind=NULL; nind=NULL; pind=NULL; hind=NULL; } } } MYfclose( fp ); //SHAVEclear_stack(); // TEXCACHEMODE=0; //clear_texcache(); } void SHAVEimport_archive_voxel( CHNG *fname, int xxx, int yyy, int zzz, HAIRTYPE * outhair, int isShadow ) { RW_CONTEXT = RW_DISK; import_archive_voxel_common( fname, xxx, yyy, zzz, outhair, isShadow ); } void SHAVEimport_mem_archive_voxel( MEMFILE * mem, int xxx, int yyy, int zzz, HAIRTYPE * outhair, int isShadow ) { RW_CONTEXT = RW_LOCAL; import_archive_voxel_common( mem, xxx, yyy, zzz, outhair, isShadow ); } int SHAVEexport_iterator( HAIRTYPE * ht ) { CURVEINFO ci; int retvar = 1; int x, xx; int yy, zz; int tverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok; int typ = -1; HAIRTYPE *outhair; SHAVEfree_hairtype( ht ); SHAVEinit_hairtype( ht ); retvar = GIThairfile; outhair = ht; //for (xx=0;xx 0 ) typ = yy; } // int zzz; // if (LOCAL_CNT[yy]>0) // for (zz=0;zz= 0 ) { yy = typ; zz = GIThairnumber; zzz = GITpassnumber; { int x, y, z; WFTYPE wf; init_geomWF( &wf ); yy = typ; SHAVEmake_a_curve( zzz, yy, zz, LOCAL_SEGS[yy], &wf, &ci ); outhair->totalverts = wf.totalverts; outhair->totalfaces = wf.totalfaces; outhair->totalfverts = wf.totalfverts; SHAVEalloc_hairtype( outhair ); outhair->totalverts = 0; outhair->totalfverts = 0; outhair->totalfaces = 0; if( ci.killme == 0 ) for( x = 0; x < wf.totalfaces; x++ ) { outhair->face_start[tf] = tfv; outhair->radiusroot[tf] = ci.baserad; outhair->radiustip[tf] = ci.tiprad; outhair->colorroot[tf] = wf.color[wf.face_start[x]]; outhair->colortip[tf] = wf.color[wf.face_end[x] - 1]; outhair->spec[tf] = sliders[4][yy].value; outhair->gloss[tf] = sliders[5][yy].value; outhair->surfNorm[tf] = ci.norm; outhair->ambdiff[tf] = sliders[6][yy].value; if( LOCAL_PASSES[yy] > 0 ) outhair->opacity[tf] = ( 1.0f / ( float ) LOCAL_PASSES[yy] ); else outhair->opacity[tf] = 0.0f; if( outhair->opacity[tf] > 1.0f ) outhair->opacity[tf] = 1.0f; if( outhair->opacity[tf] < 0.0f ) outhair->opacity[tf] = 0.0f; for( y = wf.face_start[x]; y < wf.face_end[x]; y++ ) { int g; float rad; float interp; g = wf.facelist[y]; outhair->facelist[tfv] = tv; outhair->v[tv] = wf.v[g]; outhair->uvw[tv] = wf.uv[g]; outhair->velocity[tv] = wf.velocity[g]; // outhair->velocity[tv].z *= -1.0f; // SHAVEcoord_convertFROMSHAVE( &outhair->velocity[tv] ); tv++; tfv++; outhair->totalverts++; outhair->totalfverts++; } outhair->face_end[tf] = tfv; outhair->totalfaces++; tf++; } free_geomWF( &wf ); } //for (zz=0;zz= LOCAL_CNT[typ]*LOCAL_PASSES[typ] ) { zz = 0; GIThairnumber = zz; // zzz++; // increment passes // if( zzz >= LOCAL_PASSES[typ] ) { GIThairfile++; GIThairnumber = 0; GITpassnumber = 0; zz = 0; zzz = 0; } // copy the wftype info into HAIRTYPE GITpassnumber = zzz; } // for (zzz=0;zzz= totalhairfiles ) { retvar = -1; // we are done GIThairfile = 0; GIThairnumber = 0; GITpassnumber = 0; } } if( typ < 0 ) retvar = 0; ok = retvar; return ( ok ); } void SHAVEreset_iterator( void ) { GIThairfile = 0; GIThairnumber = 0; GITpassnumber = 0; } int SHAVEexport_iteratorROOT( HAIRTYPE * ht ) { CURVEINFO ci; int retvar = 1; int x, xx; int yy, zz; int tverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok; int typ = -1; HAIRTYPE *outhair; SHAVEfree_hairtype( ht ); SHAVEinit_hairtype( ht ); retvar = GIThairfile; outhair = ht; //for (xx=0;xx 0 ) typ = yy; } // int zzz; // if (LOCAL_CNT[yy]>0) // for (zz=0;zz= 0 ) { yy = typ; zz = GIThairnumber; zzz = GITpassnumber; { int x, y, z; WFTYPE wf; init_geomWF( &wf ); SHAVEmake_a_curveROOT( zzz, yy, zz, &wf, &ci ); outhair->totalverts = wf.totalverts; outhair->totalfaces = wf.totalfaces; outhair->totalfverts = wf.totalfverts; SHAVEalloc_hairtype( outhair ); outhair->totalverts = 0; outhair->totalfverts = 0; outhair->totalfaces = 0; if( ci.killme == 0 ) for( x = 0; x < wf.totalfaces; x++ ) { outhair->surfNorm[tf] = ci.norm; outhair->face_start[tf] = tfv; outhair->radiusroot[tf] = ci.baserad; outhair->radiustip[tf] = ci.tiprad; outhair->colorroot[tf] = wf.color[wf.face_start[x]]; outhair->colortip[tf] = wf.color[wf.face_end[x] - 1]; outhair->spec[tf] = sliders[4][yy].value; outhair->gloss[tf] = sliders[5][yy].value; outhair->ambdiff[tf] = sliders[6][yy].value; if( LOCAL_PASSES[yy] > 0 ) outhair->opacity[tf] = ( 1.0f / ( float ) LOCAL_PASSES[yy] ); else outhair->opacity[tf] = 0.0f; if( outhair->opacity[tf] > 1.0f ) outhair->opacity[tf] = 1.0f; if( outhair->opacity[tf] < 0.0f ) outhair->opacity[tf] = 0.0f; for( y = wf.face_start[x]; y < wf.face_end[x]; y++ ) { int g; float rad; float interp; g = wf.facelist[y]; outhair->facelist[tfv] = tv; outhair->v[tv] = wf.v[g]; outhair->uvw[tv] = wf.uv[g]; outhair->velocity[tv] = wf.velocity[g]; // outhair->velocity[tv].z *= -1.0f; // SHAVEcoord_convertFROMSHAVE( &outhair->velocity[tv] ); tv++; tfv++; outhair->totalverts++; outhair->totalfverts++; } outhair->face_end[tf] = tfv; outhair->totalfaces++; tf++; } free_geomWF( &wf ); } //for (zz=0;zz= LOCAL_CNT[typ]*LOCAL_PASSES[typ] ) { zz = 0; GIThairnumber = zz; zzz++; // increment passes // if( zzz >= LOCAL_PASSES[typ] ) { GIThairfile++; GIThairnumber = 0; GITpassnumber = 0; zz = 0; zzz = 0; } // copy the wftype info into HAIRTYPE GITpassnumber = zzz; } // for (zzz=0;zzz= totalhairfiles ) { retvar = -1; // we are done GIThairfile = 0; GIThairnumber = 0; GITpassnumber = 0; } } if( typ < 0 ) retvar = 0; ok = retvar; return ( ok ); } int SHAVEexport_poly_iterator( HAIRTYPE * ht ) { CURVEINFO ci; int retvar = 1; int x, xx; int yy, zz; int tverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok; int typ = -1; HAIRTYPE *outhair; SHAVEfree_hairtype( ht ); SHAVEinit_hairtype( ht ); retvar = GIThairfile; outhair = ht; //for (xx=0;xx 0 ) typ = yy; } // int zzz; // if (LOCAL_CNT[yy]>0) // for (zz=0;zz= 0 ) { yy = typ; zz = GIThairnumber; zzz = GITpassnumber; { int x, y, z; WFTYPE wf, wf2; init_geomWF( &wf ); init_geomWF( &wf2 ); SHAVEmake_a_curveROOT( zzz, yy, zz, &wf2, &ci ); SHAVEmake_a_hair( zzz, yy, zz, LOCAL_SEGS[yy], &wf ); free_geomWF( &wf2 ); outhair->totalverts = wf.totalverts; outhair->totalfaces = wf.totalfaces; outhair->totalfverts = wf.totalfverts; SHAVEalloc_hairtype( outhair ); outhair->totalverts = 0; outhair->totalfverts = 0; outhair->totalfaces = 0; if( ci.killme == 0 ) for( x = 0; x < wf.totalfaces; x++ ) { outhair->face_start[tf] = tfv; outhair->radiusroot[tf] = ci.baserad; outhair->radiustip[tf] = ci.tiprad; outhair->colorroot[tf] = wf.color[wf.face_start[x]]; outhair->colortip[tf] = wf.color[wf.face_end[x] - 1]; outhair->spec[tf] = sliders[4][yy].value; outhair->gloss[tf] = sliders[5][yy].value; outhair->ambdiff[tf] = sliders[6][yy].value; if( LOCAL_PASSES[yy] > 0 ) outhair->opacity[tf] = ( 1.0f / ( float ) LOCAL_PASSES[yy] ); else outhair->opacity[tf] = 0.0f; if( outhair->opacity[tf] > 1.0f ) outhair->opacity[tf] = 1.0f; if( outhair->opacity[tf] < 0.0f ) outhair->opacity[tf] = 0.0f; for( y = wf.face_start[x]; y < wf.face_end[x]; y++ ) { int g; float rad; float interp; g = wf.facelist[y]; outhair->facelist[tfv] = tv; outhair->v[tv] = wf.v[g]; outhair->uvw[tv] = wf.uv[g]; outhair->velocity[tv] = wf.velocity[g]; // outhair->velocity[tv].z *= -1.0f; // SHAVEcoord_convertFROMSHAVE( &outhair->velocity[tv] ); tv++; tfv++; outhair->totalverts++; outhair->totalfverts++; } outhair->face_end[tf] = tfv; outhair->totalfaces++; tf++; } free_geomWF( &wf ); } //for (zz=0;zz= LOCAL_CNT[typ] ) { zz = 0; GIThairnumber = zz; zzz++; // increment passes if( zzz >= LOCAL_PASSES[typ] ) { GIThairfile++; GIThairnumber = 0; GITpassnumber = 0; zz = 0; zzz = 0; } // copy the wftype info into HAIRTYPE GITpassnumber = zzz; } // for (zzz=0;zzz= totalhairfiles ) { retvar = -1; // we are done GIThairfile = 0; GIThairnumber = 0; GITpassnumber = 0; } } if( typ < 0 ) retvar = 0; ok = retvar; return ( ok ); } void SHAVEfree_UV( UVSETS * uv ) { if( uv->totalUVSets > 0 ) if( uv->totalRoots ) if( uv->uvRoot ) if( uv->channelRef ) { free( uv->channelRef ); free( uv->uvRoot ); } uv->totalRoots = 0; uv->totalUVSets = 0; SHAVEinit_UV( uv ); } void SHAVEinit_UV( UVSETS * uv ) { { uv->channelRef = NULL; uv->uvRoot = NULL; } uv->totalRoots = 0; uv->totalUVSets = 0; } static void import_archive_voxel_by_node_common( void *indata, int xxx, int yyy, int zzz, HAIRTYPE * outhair, UVSETS * outuv, int isShadow, int node_id ) { void *fp = NULL; int x, xx; int yy; int tverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok; VERT rbound1, rbound2; int y; unsigned int pos_lookup; int voxres; VERT obound1, obound2; VOXCOUNT ev; int *hind = NULL, *pind = NULL, *nind = NULL, *slgind = NULL; outuv->channelRef = NULL; outuv->totalRoots = 0; outuv->totalUVSets = 0; outuv->uvRoot = NULL; SHAVEinit_hairtype( outhair ); SHAVEfree_hairtype( outhair ); SHAVEmutex_lock(&Gtile_render_mutex); TEXCACHEMODE=1; #ifdef DOUNICODE fp = MYfopen( indata, L"r+b" ); #else fp = MYfopen( indata, "r+b" ); #endif // fprintf(stdout,"DEBUG: fetching voxel %d %d %d nodeid %d \n",xxx,yyy,zzz,node_id);fflush(stdout); //if (0==1) if( fp ) { int tverts = 0, tfverts = 0, tfaces = 0; unsigned int t; unsigned char fileversion = 'a'; unsigned char softwareversion = 'a'; unsigned int current_pos; int zvox; int list_total=0; int *list; MYfread( &fileversion, 1, 1, fp ); MYfread( &softwareversion, 1, 1, fp ); MYfread( &t, 4, 1, fp ); // vox table dimensions voxres = t; zvox=(voxres-1)+(voxres-1)*voxres+(voxres-1)*voxres*voxres; //printf ("voxres = %d\n",voxres); MYfread( &t, 4, 1, fp ); // stackfileposition x = xxx + yyy * voxres + zzz * voxres * voxres; if( x < 0 ) x = 0; if( x > zvox ) x = zvox; MYfseek( fp, x * 4 * 2 + 9 + 1, SEEK_SET ); { t = 0; MYfread( &t, 4, 1, fp ); // high order - placeholders for the file pos addresses MYfread( &t, 4, 1, fp ); // low order pos_lookup = ( int ) t; // printf ("pos_lookup = %d\n",pos_lookup); } // for (x=0;x<20*20*20;x++) { int aa = 0; int a; unsigned int b; int bb; int tfv = 0; int cur_mult; int cur_group; tf = 0, tv = 0; current_pos = pos_lookup; MYfseek( fp, current_pos, SEEK_SET ); bb = 0; MYfread( &bb, 4, 1, fp ); // total_faces placeholder ev.totalfaces2 = ( int ) bb; //printf ("in bb = %d\n",bb); //fprintf (stdout,"ev.totalfaces2 = %d\n",ev.totalfaces2);fflush(stdout); MYfread( &obound1.x, 4, 1, fp ); // this is the bounding box of the voxel MYfread( &obound1.y, 4, 1, fp ); MYfread( &obound1.z, 4, 1, fp ); MYfread( &obound2.x, 4, 1, fp ); MYfread( &obound2.y, 4, 1, fp ); MYfread( &obound2.z, 4, 1, fp ); MYfread( &tfaces, 4, 1, fp ); MYfread( &tfverts, 4, 1, fp ); MYfread( &tverts, 4, 1, fp ); // MYfread(&tfaces,4,1,fp); list=(int *) malloc((ev.totalfaces2+40)*sizeof(int)); //printf ("tverts = %d\n",tverts); outhair->totalfaces = 0; outhair->totalfverts = 0; outhair->totalverts = 0; a = ev.totalfaces2; a += 40; hind = ( int * ) malloc( a * sizeof( int ) ); nind = ( int * ) malloc( a * sizeof( int ) ); pind = ( int * ) malloc( a * sizeof( int ) ); slgind = ( int * ) malloc( a * sizeof( int ) ); for( a = 0; a < ev.totalfaces2; a++ ) { hind[a] = 0; nind[a] = 0; pind[a] = 0; slgind[a] = 0; } aa = 0; //if (0==1) { int lastn = -1; for( a = 0; a < ev.totalfaces2; a++ ) // all the hairs in this voxel { CURVEINFO ci; WFTYPE wf; init_geomWF( &wf ); MYfread( &nind[a], 4, 1, fp ); // here's the info we'll need for a regen MYfread( &pind[a], 4, 1, fp ); MYfread( &hind[a], 4, 1, fp ); MYfread( &slgind[a], 4, 1, fp ); if( nind[a] == node_id ) if( nind[a] != ( int ) GnodeID ) { fetch_hair( nind[a], 0.0 ); // GnodeID = nind[a]; //fprintf(stdout,"DEBUG: totalhairfiles %d totalfaces %d totalverts %d totalfverts %d\n",totalhairfiles,totalfaces,totalverts,totalfverts);fflush(stdout); } if( nind[a] == node_id ) { Gpass = pind[a]; Gpass=0; // if( ( isShadow == 1 ) && ( hind[a] < LOCAL_SHADCNT[slgind[a]] ) ) //// SHAVEmake_a_curve( pind[a], slgind[a], hind[a], 1, &wf, &ci ); // SHAVEmake_a_curveROOT( 0, slgind[a], hind[a], &wf, &ci ); // if( isShadow == 0 ) // SHAVEmake_a_curve( pind[a], slgind[a], hind[a], 1, &wf, &ci ); SHAVEmake_a_curveROOT( 0, slgind[a], hind[a], &wf, &ci ); cur_mult=wf.totalfaces; cur_group=slgind[a]; list[list_total]=hind[a]; //snorms[list_total]=ci.norm; list_total++; //printf ("uv[0] = %f %f %f\n",ci.UV[0].x,ci.UV[0].y,ci.UV[0].z); //printf ("totalverts = %d totalfaces = %d\n",wf.totalverts,wf.totalfaces); } if( nind[a] == node_id ) { outuv->totalRoots += wf.totalfaces; // printf("outuv %d\n",outuv->totalRoots); } free_geomWF( &wf ); } } SHAVEinit_hairtype(outhair); if (list_total>0) { // int xx; // for (xx=0;xx<50;xx++) // if(Gshavep[node_id].uv_link[xx]>=0) outuv->totalUVSets = Guv_totalsets; // outuv->totalUVSets++; } outuv->uvRoot=NULL; outuv->channelRef = NULL; if (list_total>0) if( outuv->totalUVSets > 0 ) { outuv->channelRef = ( char * ) malloc( outuv->totalUVSets * outuv->totalRoots * sizeof( char ) ); outuv->uvRoot = ( VERT * ) malloc( outuv->totalUVSets * outuv->totalRoots * sizeof( VERT ) ); } if (list_total>0) { int lastn = -1; int qroot = 0; WFTYPE wf; CURVEINFO cinfo; init_geomWF(&wf); MTbunch_of_hairs(list_total,list,cur_group,0, &wf,&cinfo); if (freeze.totalverts>0) make_normalsWF( &wf ); outhair->totalverts=wf.totalverts; outhair->totalfverts=wf.totalfverts; outhair->totalfaces=wf.totalfaces; SHAVEalloc_hairtype(outhair); for (x=0;xv[x]=wf.v[x]; outhair->surfNorm[x]=wf.vn[x]; // outhair->color[x]=wf.color[x]; outhair->velocity[x]=wf.velocity[x]; } for (x=0;xfacelist[x]=wf.facelist[x]; } for (x=0;xsurfNorm[x]=snorm[x] outhair->index[x]=wf.index[x]; // outhair->ambdiff[x]=cinfo.ambient; // outhair->gloss[x]=cinfo.kspec; // outhair->spec[x]=cinfo.spec; outhair->spec[x] = sliders[4][cur_group].value; outhair->gloss[x] = sliders[5][cur_group].value; outhair->ambdiff[x] = sliders[6][cur_group].value; outhair->opacity[x]= 1.0f / ( float ) LOCAL_PASSES[cur_group]; outhair->face_start[x]=wf.face_start[x]; outhair->face_end[x]=wf.face_end[x]; if (freeze.totalverts==0) { outhair->radiusroot[x]=wf.r1[x]; outhair->radiustip[x]=wf.r2[x]; outhair->colorroot[x]=wf.color[wf.facelist[wf.face_start[x]]]; outhair->colortip[x]=wf.color[wf.facelist[wf.face_end[x]-1]]; } } free_geomWF(&wf); } // still need to pass through UVs } //if (ev.totalfaces) //printf ("the voxel tags were read - %d\n",ev.totalfaces); { if (slgind) free( slgind ); if (nind) free( nind ); if (pind) free( pind ); if (hind) free( hind ); } MYfclose( fp ); } //clear_texcache(); TEXCACHEMODE=0; SHAVEmutex_unlock(&Gtile_render_mutex); } extern void PRIMimport_archive_voxel_by_node( CHNG *fname, int xxx, int yyy, int zzz, HAIRTYPE * outhair, UVSETS * outuv, int isShadow, int node_id ) { RW_CONTEXT = RW_DISK; import_archive_voxel_by_node_common( fname, xxx, yyy, zzz, outhair, outuv, isShadow, node_id ); if( RW_CONTEXT != RW_DISK ) printf( "*** WARNING *** Shave: RW_CONTEXT is no longer set to RW_DISK on return from SHAVEimport_archive_voxel_by_node\n" ); } void SHAVEimport_archive_voxel_by_node( char *fname, int xxx, int yyy, int zzz, HAIRTYPE * outhair, UVSETS * outuv, int isShadow, int node_id ) { RW_CONTEXT = RW_DISK; import_archive_voxel_by_node_common( fname, xxx, yyy, zzz, outhair, outuv, isShadow, node_id ); if( RW_CONTEXT != RW_DISK ) printf( "*** WARNING *** Shave: RW_CONTEXT is no longer set to RW_DISK on return from SHAVEimport_archive_voxel_by_node\n" ); } void SHAVEimport_mem_archive_voxel_by_node( MEMFILE * mem, int xxx, int yyy, int zzz, HAIRTYPE * outhair, UVSETS * outuv, int isShadow, int node_id ) { RW_CONTEXT = RW_LOCAL; import_archive_voxel_by_node_common( mem, xxx, yyy, zzz, outhair, outuv, isShadow, node_id ); if( RW_CONTEXT != RW_LOCAL ) printf( "*** WARNING *** Shave: RW_CONTEXT is no longer set to RW_LOCAL on return from SHAVEimport_mem_archive_voxel_by_node\n" ); } int SHAVEexport_archive( CHNG *fname, int voxres ) { FILE *fp = NULL; int ret = 1; VERT root_pos; int lastn = -1; int x = 0; int tverts = 0; int tfaces = 0; int tv = 0, tf = 0, tfv = 0; int ok = 0; VERT rbound1, rbound2; int y = 0; int Nid = 0, Hid = 0, SLGid = 0, Pid = 0; int cnnt = 0; int maxv = 26 * 26 * 26; int maxv1 = 27 * 27 * 27; VOXCOUNT *ev = NULL; VOXCOUNT *ev2 = NULL; VERT *vbound1 = NULL; VERT *vbound2 = NULL; int **hind = NULL, **pind = NULL, **nind = NULL, **slgind = NULL; int done = 0; int temp; int voxthresh=7000; int zvox; // write the stack objects //for (x=0;x3) voxres=3; // anything more than 3 seems excessive ?? { int z; for( x = 0; x < maxv1; x++ ) { ev[x].totalverts = 0; ev[x].totalfverts = 0; ev[x].totalfaces = 0; ev[x].totalfaces2 = 0; ev2[x].totalverts = 0; ev2[x].totalfverts = 0; ev2[x].totalfaces = 0; ev2[x].totalfaces2 = 0; hind[x] = NULL; nind[x] = NULL; pind[x] = NULL; slgind[x] = NULL; vbound1[x].x = 10000000.0f; vbound1[x].y = 10000000.0f; vbound1[x].z = 10000000.0f; vbound2[x].x = -10000000.0f; vbound2[x].y = -10000000.0f; vbound2[x].z = -10000000.0f; } } rbound1.x = 1000000.0f; rbound1.y = 1000000.0f; rbound1.z = 1000000.0f; rbound2.x = -1000000.0f; rbound2.y = -1000000.0f; rbound2.z = -1000000.0f; // [hairfile][group] for( Nid = 0; Nid < totalhairfiles; Nid++ ) for( x = 0; x < 60; x++ ) Gtex_channellink[( int ) Nid][x] = -1; // ok, first lets size the initial bounds using all the roots // for the whole hair cube - if (GLOBAL_VERBOSE) { fprintf(stdout, "exporting archive 1\n" ); fflush( stdout ); } if( voxres > 0 ) for( Nid = 0; Nid < totalhairfiles; Nid++ ) if( done == 0 ) { CURVEINFO ci; WFTYPE wf; init_geomWF( &wf ); // printf ("fetching %d\n",Nid); fetch_hair( Nid, 0.0 ); estimated_total = ( LOCAL_CNT[0] * LOCAL_PASSES[0] ) + ( LOCAL_CNT[4] * LOCAL_PASSES[0] ); estimated_total /= 100; global_progress = 0; #ifdef progress_update if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; #endif if( done == 0 ) for( SLGid = 0; SLGid < 5; SLGid++ ) Gtex_totalchannels[Nid][SLGid] = 0; for( SLGid = 0; SLGid < 5; SLGid++ ) if( done == 0 ) { if( LOCAL_PASSES[SLGid] > 0 ) if( LOCAL_CNT[SLGid] > 0 ) { float rr = 0.0f, gg = 0.0f, bb = 0.0f; VERT pos; GnodeID = Nid; GhairID = Hid; Gslg = SLGid; Gpass = Pid; SHAVEmake_a_curveROOT( 0, SLGid, 1, &wf, &ci ); //++ SHAVEmake_a_curve(0,SLGid,Hid,1,&wf,&ci); #ifdef progress_update cnnt++; if( cnnt > 100 ) { if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; cnnt = 0; } #endif // If the hair was killed, there is no geometry to work from // in that case simply pass a null vector as the root position. if( wf.totalfaces==0 ) pos.x = pos.y = pos.z = 0.0f; else pos = wf.v[0]; for( x = 0; x < 60; x++ ) { float qt; qt = SHAVEapply_texture( &ci, pos, SHAVEID, x, -1000000.0f ); // if (x==9) rr=qt; // if (x==10) gg=qt; // if (x==11) bb=qt; if( qt >= -999999.0f ) { Gtex_channellink[( int ) Nid][x] = Gtex_totalchannels[Nid][SLGid]; Gtex_totalchannels[Nid][SLGid]++; } } } global_progress = 0; #ifdef progress_update if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; #endif Pid=0; temp=LOCAL_CNT[SLGid]*LOCAL_PASSES[SLGid]; if (temp>10000) temp=10000; if( LOCAL_PASSES[SLGid] > 0 ) if( LOCAL_CNT[SLGid] > 0 ) for( Hid = 0; Hid < temp; Hid++ ) // for( Pid = 0; Pid < LOCAL_PASSES[SLGid]; Pid++ ) if( done == 0 ) { // printf ("making curve %d %d %d\n",Pid,SLGid,Hid); GnodeID = Nid; GhairID = Hid; Gslg = SLGid; Gpass = Pid; #ifdef progress_update cnnt++; if( cnnt > 100 ) { if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; cnnt = 0; } #endif { VERT cmp; SHAVEmake_a_curveROOT( Pid, SLGid, Hid, &wf, &ci ); // fprintf (stdout,"totalfaces = %d totalverts = %d\n",wf.totalfaces,wf.totalverts);fflush(stdout); // if (ci.killme==0) // cmp=wf.v[0]; //++ SHAVEmake_a_curve( Pid, SLGid, Hid,1, &wf,&ci ); // if (ci.killme==0) // if ( // (wf.v[0].x!=cmp.x)|| // (wf.v[0].y!=cmp.y)|| // (wf.v[0].z!=cmp.z)) // printf ("Hid = %d r%f %f %f c%f %f %f\n",Hid,cmp.x,cmp.y,cmp.z,wf.v[0].x,wf.v[0].y,wf.v[0].z); } // else // SHAVEmake_a_hair( Pid, SLGid, // Hid, // LOCAL_SEGS // [SLGid], // &wf ); if( wf.totalfaces > 0 ) { // expand the bounds int x; // for (x=0;x rbound2.x ) rbound2.x = ind.x; if( ind.y > rbound2.y ) rbound2.y = ind.y; if( ind.z > rbound2.z ) rbound2.z = ind.z; } } } } free_geomWF( &wf ); } //might need to expand these some if( done == 0 ) { if( rbound2.x - rbound1.x == 0.0f ) rbound2.x += 1.0f; if( rbound2.y - rbound1.y == 0.0f ) rbound2.y += 1.0f; if( rbound2.z - rbound1.z == 0.0f ) rbound2.z += 1.0f; { float dx,dy,dz; VERT arbound1,arbound2; dx=rbound2.x-rbound1.x; dy=rbound2.y-rbound1.y; dz=rbound2.z-rbound1.z; arbound1=rbound1; arbound2=rbound2; arbound1.x-=dx/2.0f; arbound1.y-=dy/2.0f; arbound1.z-=dz/2.0f; arbound1.x-=rbound1.x; arbound1.y-=rbound1.y; arbound1.z-=rbound1.z; arbound2.x-=dx/2.0f; arbound2.y-=dy/2.0f; arbound2.z-=dz/2.0f; arbound2.x-=rbound1.x; arbound2.y-=rbound1.y; arbound2.z-=rbound1.z; arbound1.x*=1.2; arbound1.y*=1.2; arbound1.z*=1.2; arbound1.x+=dx/2.0f; arbound1.y+=dy/2.0f; arbound1.z+=dz/2.0f; arbound1.x+=rbound1.x; arbound1.y+=rbound1.y; arbound1.z+=rbound1.z; arbound2.x+=dx/2.0f; arbound2.y+=dy/2.0f; arbound2.z+=dz/2.0f; arbound2.x+=rbound1.x; arbound2.y+=rbound1.y; arbound2.z+=rbound1.z; rbound1=arbound1; rbound2=arbound2; } if (GLOBAL_VERBOSE) { fprintf(stdout, "exporting archive 2\n" ); fflush( stdout ); } //printf ("allocating texture tables\n"); if( voxres > 0 ) for( x = 0; x < totalhairfiles; x++ ) // ok we're going to allocate the texture cache tables for( y = 0; y < 5; y++ ) { int t; // t = Gtex_totalchannels[x][y] * Gshavep[x].haircount[y] ; t = Gtex_totalchannels[x][y] * Gshavep[x].haircount[y] * ( Gshavep[x].passes[y] ); //printf ("t = %d\n",t); //if (t!=0) t += 40; Gtex_cacheinfo[x][y] = ( float * ) malloc( t * sizeof( float ) ); t = Gshavep[x].haircount[y] * ( Gshavep[x].passes[y] ); // t = Gshavep[x].haircount[y] ; t += 40; //if (t!=0) Gtex_cachedisplace[x][y] = ( VERT * ) malloc( t * sizeof( VERT ) ); } } //fflush(stdout); if (GLOBAL_VERBOSE) { fprintf(stdout, "exporting archive 3\n" ); fflush( stdout ); } #ifdef progress_update global_progress = 0; if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; #endif // ok, now we count the number of hair hits/verts per cube //if (rbound1.x+rbound1.y+rbound1.z+rbound2.x+rbound2.y+rbound2.z > 0) //printf ("rbound %f %f %f - %f %f %f\n",rbound1.x,rbound1.y,rbound1.z,rbound2.x,rbound2.y,rbound2.z); if( voxres > 0 ) for( Nid = 0; Nid < totalhairfiles; Nid++ ) if( done == 0 ) { CURVEINFO ci; WFTYPE wf; fetch_hair( Nid, 0.0 ); estimated_total = ( LOCAL_CNT[0] * LOCAL_PASSES[0] ) + ( LOCAL_CNT[4] * LOCAL_PASSES[0] ); estimated_total /= 100; #ifdef progress_update global_progress = 0; if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; #endif Pid=0; if( done == 0 ) for( SLGid = 0; SLGid < 5; SLGid++ ) if( done == 0 ) { if( LOCAL_CNT[SLGid] > 0 ) for( Hid = 0; Hid < LOCAL_CNT[SLGid]*LOCAL_PASSES[SLGid]; Hid++ ) // for( Pid = 0; Pid < LOCAL_PASSES[SLGid]; Pid++ ) if( done == 0 ) { VERT dsp; int a; init_geomWF( &wf ); GnodeID = Nid; GhairID = Hid; Gslg = SLGid; Gpass = Pid; #ifdef progress_update cnnt++; if( cnnt > 100 ) { if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; cnnt = 0; } #endif SHAVEmake_a_curveROOT( Pid, SLGid, Hid, &wf, &ci ); // fprintf (stdout,"totalfaces = %d totalverts = %d\n",wf.totalfaces,wf.totalverts);fflush(stdout); //++ SHAVEmake_a_curve(Pid,SLGid,Hid,1,&wf,&ci); if( wf.totalverts > 0 ) root_pos = wf.v[0]; if( wf.totalverts > 0 ) dsp = SHAVEdisplace_root( &root_pos, &ci, SHAVEID ); if( wf.totalverts > 0 ) Gtex_cachedisplace[Nid][SLGid][Hid ]=dsp; //+ Gshavep[Nid].haircount[SLGid] * Pid] = dsp; if( wf.totalverts > 0 ) // if (ci->killed { float rr, gg, bb; int tt = 0; for( x = 0; x < 60; x++ ) { float qt; qt = SHAVEapply_texture( &ci, root_pos, SHAVEID, x, -1000000.0f ); if( qt >= -999999.0f ) { // Gtex_cacheinfo[Nid][SLGid][tt + Pid * Gtex_totalchannels[Nid][SLGid] + Gtex_totalchannels[Nid][SLGid] * Hid * Gshavep[Nid].passes[SLGid]] = qt; Gtex_cacheinfo[Nid][SLGid][tt + Gtex_totalchannels[Nid][SLGid] * Hid ] = qt; // if (x==9) rr=qt; // if (x==10) gg=qt; // if (x==11) bb=qt; tt++; } } } // SHAVEmake_a_curve( Pid, SLGid, // Hid, // LOCAL_SEGS // [SLGid], &wf, // &ci ); // else // if( freeze.totalverts != 0 ) // SHAVEmake_a_hair( Pid, SLGid, Hid, // LOCAL_SEGS // [SLGid], &wf ); if( wf.totalverts > 0 ) { // expand the bounds int x; float dx, dy, dz; dx = ( rbound2.x - rbound1.x ); dy = ( rbound2.y - rbound1.y ); dz = ( rbound2.z - rbound1.z ); x = 0; // for (x=0;x= voxres ) ind.x = voxres - 1; if( ind.y < 0 ) ind.y = 0; else if( ind.y >= voxres ) ind.y = voxres - 1; if( ind.z < 0 ) ind.z = 0; else if( ind.z >= voxres ) ind.z = voxres - 1; add = ( int ) ind.x + ( int ) ( ind.y * voxres ) + ( int ) ( ind.z * voxres * voxres ); if (add<0) add=0; if (add>zvox) add=zvox; // if (add>voxres*voxres*voxres-1) add=voxres*voxres*voxres-1; ev[add].totalfaces += wf.totalfaces; ev[add].totalfaces2++; ev[add].totalverts += wf.totalverts; ev[add].totalfverts += wf.totalfverts; // ev[add].totalverts+=wf.totalfaces*LOCAL_SEGS[SLGid]; // ev[add].totalfverts+=wf.totalfaces*LOCAL_SEGS[SLGid]; // printf ("add = %d\n",add); bn1 = &vbound1[add]; bn2 = &vbound2[add]; // for( a = 0; a < wf.totalverts; // a++ ) { ind = root_pos; if( ind.x < bn1->x ) bn1->x = ind.x; if( ind.y < bn1->y ) bn1->y = ind.y; if( ind.z < bn1->z ) bn1->z = ind.z; if( ind.x > bn2->x ) bn2->x = ind.x; if( ind.y > bn2->y ) bn2->y = ind.y; if( ind.z > bn2->z ) bn2->z = ind.z; } } } free_geomWF( &wf ); } } } if (GLOBAL_VERBOSE) { fprintf(stdout, "exporting archive 4\n" ); fflush( stdout ); } if( done == 0 ) if( voxres > 0 ) for( x = 0; x <= zvox; x++ ) if (ev[x].totalfaces2>0) { int a; a = ev[x].totalfaces2; a += 40; // why? // fprintf (stdout,"allocated %d in voxel %d\n",a,x);fflush(stdout); hind[x] = ( int * ) malloc( a * sizeof( int ) ); nind[x] = ( int * ) malloc( a * sizeof( int ) ); pind[x] = ( int * ) malloc( a * sizeof( int ) ); slgind[x] = ( int * ) malloc( a * sizeof( int ) ); for( a = 0; a < ev[x].totalfaces2; a++ ) { hind[x][a] = 0; nind[x][a] = 0; pind[x][a] = 0; slgind[x][a] = 0; } ev2[x] = ev[x]; ev[x].totalfaces = 0; ev[x].totalfaces2 = 0; ev[x].totalverts = 0; ev[x].totalfverts = 0; } if (GLOBAL_VERBOSE) { fprintf( stdout,"exporting archive 5\n" ); fflush( stdout ); } // ok now, er want to build up the hairID,nodeID,passID lists //printf ("ok, begin the actual export\n"); if( voxres > 0 ) for( Nid = 0; Nid < totalhairfiles; Nid++ ) if( done == 0 ) { int totchans = 0; CURVEINFO ci; WFTYPE wf; fetch_hair( Nid, 0.0 ); estimated_total = ( LOCAL_CNT[0] * LOCAL_PASSES[0] ) + ( LOCAL_CNT[4] * LOCAL_PASSES[0] ); estimated_total /= 100; #ifdef progress_update global_progress = 0; if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; #endif for( SLGid = 0; SLGid < 5; SLGid++ ) if( done == 0 ) { Pid=0; if (freeze.totalverts==0) if( LOCAL_CNT[SLGid] > 0 ) // for( Pid = 0; Pid < LOCAL_PASSES[SLGid]; Pid++ ) { for( Hid = 0; Hid < LOCAL_CNT[SLGid]*LOCAL_PASSES[SLGid]; Hid++ ) if( done == 0 ) { int a; VERT dsp; float tex_lookup[60]; int dread; int PP; dread=(int)sliders[25][SLGid].value; if (dread==0) dread=1; init_geomWF( &wf ); GnodeID = Nid; GhairID = Hid; Gslg = SLGid; Gpass = Pid; PP=Pid; if (PP<=0) PP=1; #ifdef progress_update // cnnt++; // if( cnnt > 100 ) // { // if( SHAVEprogress( global_progress, estimated_total ) == 0 ) // global_progress++; // else // done = 1; // cnnt = 0; // } #endif dsp.x = 0.0f; dsp.y = 0.0f; dsp.z = 0.0f; if (Hid < voxthresh) if( freeze.totalverts == 0 ) // this was commented SHAVEmake_a_curve( Pid, SLGid, Hid, LOCAL_SEGS[SLGid], &wf, &ci ); if (Hid >= voxthresh) if( freeze.totalverts == 0 ) // this was commented SHAVEmake_a_curveROOT( Pid, SLGid, Hid, &wf, &ci ); if( wf.totalfaces > 0 ) { CURVEINFO c2; WFTYPE ww; init_geomWF( &ww ); SHAVEmake_a_curveROOT( Pid, SLGid, Hid, &ww, &c2 ); root_pos = ww.v[0]; // if (Hid<400) // if (ww.v[0].x!=wf.v[0].x) // { // fprintf (stdout,"no match on hair %d - %f %f %f %f %f %f\n", /// Hid, // wf.v[0].x,wf.v[0].y,wf.v[0].z, // ww.v[0].x,ww.v[0].y,ww.v[0].z); // fflush(stdout); // } free_geomWF(&ww); } // else // if (ci.killme==0) if( wf.totalfaces > 0 ) { // expand the bounds int x; float dx, dy, dz; dx = ( rbound2.x - rbound1.x ); dy = ( rbound2.y - rbound1.y ); dz = ( rbound2.z - rbound1.z ); //fprintf (stdout,"total faces = %d totalverts = %d\n",wf.totalfaces,wf.totalverts);fflush(stdout); // for (x=0;x= voxres ) ind.x = voxres - 1; if( ind.y < 0 ) ind.y = 0; else if( ind.y >= voxres ) ind.y = voxres - 1; if( ind.z < 0 ) ind.z = 0; else if( ind.z >= voxres ) ind.z = voxres - 1; add = ( int ) ind.x + ( int ) ( ind.y * voxres ) + ( int ) ( ind.z * voxres * voxres ); if( add < 0 ) add = 0; if( add > zvox ) add = zvox; // if (add>voxres*voxres*voxres-1) add=voxres*voxres*voxres-1; // for (a=0;ax ) bn1->x = ind.x - rad; if( ind.y - rad < bn1->y ) bn1->y = ind.y - rad; if( ind.z - rad < bn1->z ) bn1->z = ind.z - rad; if( ind.x + rad > bn2->x ) bn2->x = ind.x + rad; if( ind.y + rad > bn2->y ) bn2->y = ind.y + rad; if( ind.z + rad > bn2->z ) bn2->z = ind.z + rad; if( ind.x + mind.x < bn1->x ) bn1->x = ind.x + mind.x; if( ind.y + mind.y < bn1->y ) bn1->y = ind.y + mind.y; if( ind.z + mind.z < bn1->z ) bn1->z = ind.z + mind.z; if( ind.x + mind.x > bn2->x ) bn2->x = ind.x + mind.x; if( ind.y + mind.y > bn2->y ) bn2->y = ind.y + mind.y; if( ind.z + mind.z > bn2->z ) bn2->z = ind.z + mind.z; } if( freeze.totalverts == 0 ) // this was commented { ev[add].totalverts += (LOCAL_SEGS[SLGid]+3)*dread; ev[add].totalfverts += (LOCAL_SEGS[SLGid]+3)*dread; // fprintf (stdout,"LOCAL2 %d wf %d dred %d\n",(LOCAL_SEGS[SLGid]+1)*dread,wf.totalfverts);fflush(stdout); } } } if (wf.totalfaces>0) free_geomWF( &wf ); } } // end passes //this is for instances Pid=0; if (freeze.totalverts!=0) if( LOCAL_CNT[SLGid] > 0 ) for( Hid = 0; Hid < LOCAL_CNT[SLGid]*LOCAL_PASSES[SLGid]; Hid++ ) // for( Pid = 0; Pid < LOCAL_PASSES[SLGid]; Pid++ ) if( done == 0 ) { int a; VERT dsp; float tex_lookup[60]; int dread; int PP; init_geomWF( &wf ); GnodeID = Nid; GhairID = Hid; Gslg = SLGid; Gpass = Pid; dread=(int)sliders[25][SLGid].value; PP=Pid; if (Pid<=0) PP=1; if (dread==0) dread=1; #ifdef progress_update cnnt++; if( cnnt > 100 ) { if( SHAVEprogress( global_progress, estimated_total ) == 0 ) global_progress++; else done = 1; cnnt = 0; } #endif dsp.x = 0.0f; dsp.y = 0.0f; dsp.z = 0.0f; if (Hid < voxthresh) if( freeze.totalverts == 0 ) // this was commented SHAVEmake_a_curve( Pid, SLGid, Hid, LOCAL_SEGS[SLGid], &wf, &ci ); if (Hid >= voxthresh) SHAVEmake_a_curveROOT( Pid, SLGid, Hid, &wf, &ci ); if( wf.totalfaces > 0 ) { CURVEINFO c2; WFTYPE ww; init_geomWF( &ww ); SHAVEmake_a_curveROOT( Pid, SLGid, Hid, &ww, &c2 ); root_pos = ww.v[0]; free_geomWF(&ww); } if( freeze.totalverts != 0 ) // I've replaced with this { SHAVEmake_a_curveROOT( Pid, SLGid, Hid, &wf, &ci ); if( wf.totalfaces > 0 ) root_pos = wf.v[0]; } // else if (Hid < voxthresh) if( freeze.totalverts != 0 ) SHAVEmake_a_hair( Pid, SLGid, Hid, LOCAL_SEGS[SLGid], &wf ); if( wf.totalverts > 0 ) dsp = SHAVEdisplace_root( &root_pos, &ci, SHAVEID ); // Gtex_cachedisplace[Nid][SLGid][Hid + Gshavep[Nid].haircount[SLGid] * Pid] = dsp; // if (ci.killme==0) if( wf.totalfaces > 0 ) { // expand the bounds int x; float dx, dy, dz; dx = ( rbound2.x - rbound1.x ); dy = ( rbound2.y - rbound1.y ); dz = ( rbound2.z - rbound1.z ); // for (x=0;x= voxres ) ind.x = voxres - 1; if( ind.y < 0 ) ind.y = 0; else if( ind.y >= voxres ) ind.y = voxres - 1; if( ind.z < 0 ) ind.z = 0; else if( ind.z >= voxres ) ind.z = voxres - 1; add = ( int ) ind.x + ( int ) ( ind.y * voxres ) + ( int ) ( ind.z * voxres * voxres ); if( add < 0 ) add = 0; if( add > zvox ) add = zvox; // if (add>voxres*voxres*voxres-1) add=voxres*voxres*voxres-1; // for (a=0;ax ) bn1->x = ind.x - rad; if( ind.y - rad < bn1->y ) bn1->y = ind.y - rad; if( ind.z - rad < bn1->z ) bn1->z = ind.z - rad; if( ind.x + rad > bn2->x ) bn2->x = ind.x + rad; if( ind.y + rad > bn2->y ) bn2->y = ind.y + rad; if( ind.z + rad > bn2->z ) bn2->z = ind.z + rad; if( ind.x + mind.x < bn1->x ) bn1->x = ind.x + mind.x; if( ind.y + mind.y < bn1->y ) bn1->y = ind.y + mind.y; if( ind.z + mind.z < bn1->z ) bn1->z = ind.z + mind.z; if( ind.x + mind.x > bn2->x ) bn2->x = ind.x + mind.x; if( ind.y + mind.y > bn2->y ) bn2->y = ind.y + mind.y; if( ind.z + mind.z > bn2->z ) bn2->z = ind.z + mind.z; } //ev[add].totalverts += wf.totalverts; //ev[add].totalfverts += wf.totalfverts; ev[add].totalverts += freeze.totalverts*dread; ev[add].totalfverts += freeze.totalfverts*dread; } } free_geomWF( &wf ); } } } if (GLOBAL_VERBOSE) { fprintf(stdout, "exporting archive 6\n" ); fflush( stdout ); } //for (x=0;x<3*3*3;x++) //{ //printf (" vbound %f %f %f %f %f %f \n",vbound1[x].x,vbound1[x].y,vbound1[x].z // ,vbound2[x].x,vbound2[x].y,vbound2[x].z); //} //printf ("begin writing now \n"); RW_CONTEXT = RW_DISK; if( done == 0 ) fp = MYfopen( fname, #ifdef DOUNICODE L"w+b" #else "w+b" #endif ); if( !fp ) { done = 1; ret = -1; } if( done == 0 ) if( fp ) { unsigned int t; unsigned char fileversion = 'j'; // spec fix upgrade to g // unsigned char fileversion = 'h'; // use_old_splayscale #ifdef EXTERNAL_COLLISION // file generated by softimage users // licenses will not be counted !! unsigned char softwareversion = 'a'; #endif #ifndef EXTERNAL_COLLISION // NOT softimage users // licenses will be counted unsigned char softwareversion = 'b'; #endif unsigned int current_pos = 0; int zvox; int additup=0; //FILE *fbounds=NULL; //fbounds=fopen("c:\\bounds.obj","w"); zvox=(voxres-1)+(voxres-1)*voxres+(voxres-1)*voxres*voxres; t = ( unsigned int ) voxres; if (GLOBAL_VERBOSE) { fprintf(stdout, "OUTvoxres = %d\n", voxres );fflush(stdout); } MYfwrite( &fileversion, 1, 1, fp ); MYfwrite( &softwareversion, 1, 1, fp ); MYfwrite( &voxres, 4, 1, fp ); // vox table dimensions MYfwrite( &t, 4, 1, fp ); // hairstack position for( x = 0; x <= zvox; x++ ) { t = 0; MYfwrite( &t, 4, 1, fp ); // high order - placeholders for the file pos addresses MYfwrite( &t, 4, 1, fp ); // low order } for( x = 0; x <= zvox; x++ ) { int a; int add; unsigned int b; int bb = 0; int tfv = 0, tf = 0, tv = 0; int lastn = -1; current_pos = ( unsigned int ) ftell( fp ); t = 9 + x * 2 * 4 + 1; add = x; fseek( fp, t, SEEK_SET ); b = current_pos; MYfwrite( &b, 4, 1, fp ); // lets assume low order = 0 for now b = current_pos; MYfwrite( &b, 4, 1, fp ); //additup+=ev[add].totalfaces; // if (ev[add].totalfaces>0) //fprintf (stdout,"writing %d in voxel %d total = %d\n",ev[add].totalfaces,x,additup);fflush(stdout); // printf ("pos_lookup = %d\n",b); fseek( fp, current_pos, SEEK_SET ); bb = ev[add].totalfaces2; MYfwrite( &bb, 4, 1, fp ); // original hairs -used to say total faces placeholder - this number does not include mults // printf ("bb = %d\n",bb); if (Grender_host==kShaveHostMR) expand_bound(&vbound1[x],&vbound2[x],Gvox_mult); // expand the bounds by 2% and square them off //printf ("OUT %d position[%d]= %d hairs in this voxel = %d \n",t,x,current_pos,bb); MYfwrite( &vbound1[x].x, 4, 1, fp ); // this is the bounding box of the voxel MYfwrite( &vbound1[x].y, 4, 1, fp ); MYfwrite( &vbound1[x].z, 4, 1, fp ); MYfwrite( &vbound2[x].x, 4, 1, fp ); MYfwrite( &vbound2[x].y, 4, 1, fp ); MYfwrite( &vbound2[x].z, 4, 1, fp ); //fprintf (fbounds,"%f %f %f / %f %f %f\n", // vbound1[x].x,vbound1[x].y,vbound1[x].z, // vbound2[x].x,vbound2[x].y,vbound2[x].z); MYfwrite( &ev[add].totalfaces, 4, 1, fp ); //fprintf (stdout," add = %d totalfaces = %d\n",add,ev[add].totalfaces);fflush(stdout); MYfwrite( &ev[add].totalfverts, 4, 1, fp ); MYfwrite( &ev[add].totalverts, 4, 1, fp ); // MYfwrite(&ev2[add].totalfaces2,4,1,fp); //fprintf (stdout, "saving voxel %d totalfaces2= %d\n",add,ev[add].totalfaces2);fflush(stdout); // what the hell is ev2 for ?? for( a = 0; a < ev2[add].totalfaces2; a++ ) // all the hairs in this voxel for( a = 0; a < ev[add].totalfaces2; a++ ) // all the hairs in this voxel { int totaltex = 0; float tex_lookup[60]; MYfwrite( &nind[add][a], 4, 1, fp ); // here's the info we'll need for a regen MYfwrite( &pind[add][a], 4, 1, fp ); MYfwrite( &hind[add][a], 4, 1, fp ); MYfwrite( &slgind[add][a], 4, 1, fp ); } // a //fprintf (stdout, "done saving voxel %d totalfaces2= %d\n",add,ev[add].totalfaces2);fflush(stdout); } //fclose(fbounds); } if (GLOBAL_VERBOSE) { fprintf(stdout, "exporting archive 7\n" ); fflush( stdout ); } //if (0==1) if( done == 0 ) if( fp ) { unsigned int current_pos; current_pos = ( unsigned int ) ftell( fp ); fseek( fp, 5 + 1, SEEK_SET ); MYfwrite( ¤t_pos, 4, 1, fp ); // position of the hairstack fseek( fp, current_pos, SEEK_SET ); MYfwrite( &totalhairfiles, 4, 1, fp ); for( x = 0; x < totalhairfiles; x++ ) { unsigned int i; int f; int qq; i = hairfiles[x].ID; MYfwrite( &i, 4, 1, fp ); i = hairfiles[x].size; MYfwrite( &i, 4, 1, fp ); f = ( int ) hairfiles[x].time; MYfwrite( &f, 4, 1, fp ); for( qq = 0; qq < hairfiles[x].size; qq++ ) { MYfwrite( &hairfiles[x].data[qq], 1, 1, fp ); } i = hairstate[x].ID; MYfwrite( &i, 4, 1, fp ); i = hairstate[x].size; MYfwrite( &i, 4, 1, fp ); f = ( int ) hairstate[x].time; MYfwrite( &f, 4, 1, fp ); for( qq = 0; qq < hairstate[x].size; qq++ ) { MYfwrite( &hairstate[x].data[qq], 1, 1, fp ); } { SHAVEPARMS *sp; sp = &Gshavep[x]; for( qq = 0; qq < 5; qq++ ) { MYfwrite( &sp->haircount[qq], 4, 1, fp ); } // fileversion c for( qq = 0; qq < 5; qq++ ) { MYfwrite( &sp->shadowHaircount[qq], 4, 1, fp ); } for( qq = 0; qq < 5; qq++ ) { MYfwrite( &sp->passes[qq], 4, 1, fp ); } for( qq = 0; qq < 5; qq++ ) { int aa; for( aa = 0; aa < 60; aa++ ) { MYfwrite( &sp->slider_val[aa][qq], 4, 1, fp ); } } for( qq = 0; qq < 5; qq++ ) { int aa, lb; for( aa = 0; aa < 60; aa++ ) { for( lb = 0; lb < 50; lb++ ) MYfwrite( &sp->slider_lable[aa][qq][lb], 1, 1, fp ); } } for( qq = 0; qq < 5; qq++ ) { int aa; for( aa = 0; aa < 60; aa++ ) { MYfwrite( &sp->painted[aa][qq], 4, 1, fp ); } } MYfwrite( &sp->total_guides, 4, 1, fp ); MYfwrite( &sp->instancing_status, 4, 1, fp ); for( qq = 0; qq < 5; qq++ ) { MYfwrite( &sp->collide[qq], 4, 1, fp ); } MYfwrite( &sp->collision_method, 4, 1, fp ); for( qq = 0; qq < 5; qq++ ) { MYfwrite( &sp->frizz_anim_dir[qq].x, 4, 1, fp ); MYfwrite( &sp->frizz_anim_dir[qq].y, 4, 1, fp ); MYfwrite( &sp->frizz_anim_dir[qq].z, 4, 1, fp ); } for( qq = 0; qq < 5; qq++ ) { MYfwrite( &sp->segs[qq], 4, 1, fp ); } MYfwrite( &sp->dontinterpolate, 4, 1, fp ); MYfwrite( &sp->geom_shadow, 4, 1, fp ); for( qq = 0; qq < 60; qq++ ) MYfwrite( &sp->uv_link[qq], 4, 1, fp ); // fileversion d for( qq = 0; qq < 64; qq++ ) MYfwrite( &sp->name[qq], 1, 1, fp ); // fileversion g // spec fix MYfwrite( &sp->spec_tint.x, 4, 1, fp ); MYfwrite( &sp->spec_tint.y, 4, 1, fp ); MYfwrite( &sp->spec_tint.z, 4, 1, fp ); // spec fix //squirrel // if( fileversion >= 'h' ) MYfwrite( &sp->squirrel, 4, 1, fp ); // fileversion h // MYfwrite( &sp->use_old_splayscale, 4, 1, fp ); // if( fileversion >= 'i' ) MYfwrite( &sp->flyaway_percent, 4, 1, fp ); MYfwrite( &sp->clumps, 4, 1, fp ); // if( fileversion >= 'i' ) MYfwrite( &sp->rand_seed_offset, 4, 1, fp ); // fileversion j // spec fix 2 MYfwrite( &sp->spec_tint2.x, 4, 1, fp ); MYfwrite( &sp->spec_tint2.y, 4, 1, fp ); MYfwrite( &sp->spec_tint2.z, 4, 1, fp ); } } // now write the camera and lights info //printf ("outbound matrix\n"); for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) { MYfwrite( &LWCamOPEN.view[x][y], 4, 1, fp ); // printf ("%f ",LWCamOPEN.view[x][y]); } //printf ("end outbound matrix\n"); for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfwrite( &LWCamOPEN.iview[x][y], 4, 1, fp ); MYfwrite( &LWCamOPEN.nearclip, 4, 1, fp ); MYfwrite( &LWCamOPEN.wind, 4, 1, fp ); MYfwrite( &LWCamOPEN.xlight, 4, 1, fp ); MYfwrite( &LWCamOPEN.shadsamps, 4, 1, fp ); MYfwrite( &LWCamOPEN.shadowcolor.x, 4, 1, fp ); MYfwrite( &LWCamOPEN.shadowcolor.y, 4, 1, fp ); MYfwrite( &LWCamOPEN.shadowcolor.z, 4, 1, fp ); MYfwrite( &LWCamOPEN.aspect, 4, 1, fp ); MYfwrite( &LWCamOPEN.id, 4, 1, fp ); MYfwrite( &LWCamOPEN.wpos.x, 4, 1, fp ); MYfwrite( &LWCamOPEN.wpos.y, 4, 1, fp ); MYfwrite( &LWCamOPEN.wpos.z, 4, 1, fp ); MYfwrite( &LWCamOPEN.fuzz, 4, 1, fp ); MYfwrite( &LWCamOPEN.xlight, 4, 1, fp ); MYfwrite( &LWCamOPEN.xres, 4, 1, fp ); MYfwrite( &LWCamOPEN.yres, 4, 1, fp ); MYfwrite( &LWCamOPEN.zoom, 4, 1, fp ); for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfwrite( &LWCamCLOSE.view[x][y], 4, 1, fp ); for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfwrite( &LWCamCLOSE.iview[x][y], 4, 1, fp ); MYfwrite( &LWCamCLOSE.nearclip, 4, 1, fp ); MYfwrite( &LWCamCLOSE.wind, 4, 1, fp ); MYfwrite( &LWCamCLOSE.xlight, 4, 1, fp ); MYfwrite( &LWCamCLOSE.shadsamps, 4, 1, fp ); MYfwrite( &LWCamCLOSE.shadowcolor.x, 4, 1, fp ); MYfwrite( &LWCamCLOSE.shadowcolor.y, 4, 1, fp ); MYfwrite( &LWCamCLOSE.shadowcolor.z, 4, 1, fp ); MYfwrite( &LWCamCLOSE.aspect, 4, 1, fp ); MYfwrite( &LWCamCLOSE.id, 4, 1, fp ); MYfwrite( &LWCamCLOSE.wpos.x, 4, 1, fp ); MYfwrite( &LWCamCLOSE.wpos.y, 4, 1, fp ); MYfwrite( &LWCamCLOSE.wpos.z, 4, 1, fp ); MYfwrite( &LWCamCLOSE.fuzz, 4, 1, fp ); MYfwrite( &LWCamCLOSE.xlight, 4, 1, fp ); MYfwrite( &LWCamCLOSE.xres, 4, 1, fp ); MYfwrite( &LWCamCLOSE.yres, 4, 1, fp ); MYfwrite( &LWCamCLOSE.zoom, 4, 1, fp ); MYfwrite( &totallights, 4, 1, fp ); { int l; for( l = 0; l < totallights; l++ ) { for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfwrite( &LWlight[l].view[x][y], 4, 1, fp ); for( x = 0; x < 4; x++ ) for( y = 0; y < 4; y++ ) MYfwrite( &LWlight[l].iview[x][y], 4, 1, fp ); MYfwrite( &LWlight[l].nearclip, 4, 1, fp ); MYfwrite( &LWlight[l].wind, 4, 1, fp ); MYfwrite( &LWlight[l].xlight, 4, 1, fp ); MYfwrite( &LWlight[l].shadsamps, 4, 1, fp ); MYfwrite( &LWlight[l].shadowcolor.x, 4, 1, fp ); MYfwrite( &LWlight[l].shadowcolor.y, 4, 1, fp ); MYfwrite( &LWlight[l].shadowcolor.z, 4, 1, fp ); MYfwrite( &LWlight[l].color.x, 4, 1, fp ); MYfwrite( &LWlight[l].color.y, 4, 1, fp ); MYfwrite( &LWlight[l].color.z, 4, 1, fp ); MYfwrite( &LWlight[l].aspect, 4, 1, fp ); MYfwrite( &LWlight[l].id, 4, 1, fp ); MYfwrite( &LWlight[l].wpos.x, 4, 1, fp ); MYfwrite( &LWlight[l].wpos.y, 4, 1, fp ); MYfwrite( &LWlight[l].wpos.z, 4, 1, fp ); MYfwrite( &LWlight[l].fuzz, 4, 1, fp ); MYfwrite( &LWlight[l].xlight, 4, 1, fp ); MYfwrite( &LWlight[l].xres, 4, 1, fp ); MYfwrite( &LWlight[l].yres, 4, 1, fp ); MYfwrite( &LWlight[l].zoom, 4, 1, fp ); } } // now we want to write the texture cache { for( x = 0; x < totalhairfiles; x++ ) { for( y = 0; y < 5; y++ ) { MYfwrite( &Gtex_totalchannels[x][y], 4, 1, fp ); } } for( y = 0; y < 60; y++ ) { for( x = 0; x < totalhairfiles; x++ ) { // #ifdef ALTERNATE_DEFS // printf("chan link at save = %d\n", Gtex_channellink[x][y]); // fflush(stdout); // #endif MYfwrite( &Gtex_channellink[x][y], 4, 1, fp ); } } for( x = 0; x < totalhairfiles; x++ ) for( y = 0; y < 5; y++ ) { int t; int z; t = Gtex_totalchannels[x][y] * Gshavep[x].passes[y] * Gshavep[x].haircount[y]; // t = Gtex_totalchannels[x][y] * Gshavep[x].haircount[y]; for( z = 0; z < t; z++ ) { MYfwrite( &Gtex_cacheinfo[x][y][z], 4, 1, fp ); } t = Gshavep[x].passes[y] * Gshavep[x].haircount[y]; // t = Gshavep[x].haircount[y]; for( z = 0; z < t; z++ ) { // MYfwrite( &Gtex_cachedisplace[x][y][z], 4, 1, // fp ); MYfwrite( &Gtex_cachedisplace[x][y][z].x, 4, 1, fp ); MYfwrite( &Gtex_cachedisplace[x][y][z].y, 4, 1, fp ); MYfwrite( &Gtex_cachedisplace[x][y][z].z, 4, 1, fp ); } } } // now, we want to write out the occlusion mesh //if (0==1) if( GLOBALocclude ) { int x; int zr = 0; MYfwrite( &GLOBALocclude->totalverts, 4, 1, fp ); MYfwrite( &GLOBALocclude->totalfverts, 4, 1, fp ); MYfwrite( &GLOBALocclude->totalfaces, 4, 1, fp ); MYfwrite( &zr, 4, 1, fp ); // leave room for some more params MYfwrite( &zr, 4, 1, fp ); for( x = 0; x < GLOBALocclude->totalverts; x++ ) { MYfwrite( &GLOBALocclude->v[x].x, 4, 1, fp ); MYfwrite( &GLOBALocclude->v[x].y, 4, 1, fp ); MYfwrite( &GLOBALocclude->v[x].z, 4, 1, fp ); MYfwrite( &GLOBALocclude->velocity[x].x, 4, 1, fp ); MYfwrite( &GLOBALocclude->velocity[x].y, 4, 1, fp ); MYfwrite( &GLOBALocclude->velocity[x].z, 4, 1, fp ); //MYfwrite(&GLOBALocclude->uv[x].x,4,1,fp); // this should really be per-fvert //MYfwrite(&GLOBALocclude->uv[x].y,4,1,fp); //MYfwrite(&GLOBALocclude->uv[x].z,4,1,fp); } for( x = 0; x < GLOBALocclude->totalfverts; x++ ) { MYfwrite( &GLOBALocclude->facelist[x], 4, 1, fp ); } for( x = 0; x < GLOBALocclude->totalfaces; x++ ) { MYfwrite( &GLOBALocclude->face_start[x], 4, 1, fp ); MYfwrite( &GLOBALocclude->face_end[x], 4, 1, fp ); } } else { int zr = 0; MYfwrite( &zr, 4, 1, fp ); MYfwrite( &zr, 4, 1, fp ); MYfwrite( &zr, 4, 1, fp ); MYfwrite( &zr, 4, 1, fp ); MYfwrite( &zr, 4, 1, fp ); } // done } //printf ("done with the archive writing\n"); if (GLOBAL_VERBOSE) { fprintf( stdout,"exporting archive 8\n" ); fflush( stdout ); } //if (done==0) if( fp ) for( x = 0; x