// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 #define MOUSE1 101 /* BUT100 */ #define MOUSE2 102 /* BUT101 */ #define MOUSE3 103 /* BUT102 */ #define MOUSE_PAN 333 /* BUT102 */ #define MOUSE_ZOOM 334 /* BUT102 */ #define MOUSE_PICK 335 /* BUT102 */ #define MOUSE_ORBIT 336 /* BUT102 */ #include static void init_freeze( void ); static void undo_op( void ); static void setupVOX( char filename[255] ); static void cut_hair( void ); static void select_down( int ); static void select_up( int ); static void center_all( void ); static VERT find_vector( VERT a, VERT b ) { VERT ret; float d, dx, dy, dz; dx = b.x - a.x; dy = b.y - a.y; dz = b.z - a.z; d = ( float ) sqrt( dx * dx + dy * dy + dz * dz ); if( d != 0 ) { dx /= d; dy /= d; dz /= d; } ret.x = dx; ret.y = dy; ret.z = dz; return ( ret ); } #include "math.h" static void build_font( void ); static void interactive( void ); #include static void hide( void ); static void unhide( void ); static void M_selmode_invert( void ); static void M_selmode_roots( void ); static void M_selmode_ends( void ); static void M_selmode_verts( void ); #ifdef SOFTIMAGE #ifdef BROKEN void _sliidi( void ) { } void _sliien( char *a ) { } void _sliiwr( int a, int b, char *c ) { } void _sliird( int a, int b, char *c ) { } #endif #endif #ifndef _WIN32 void _sliidi( void ) { } void _sliien( char *a ) { } void _sliiwr( int a, int b, char *c ) { } void _sliird( int a, int b, char *c ) { } #endif #ifdef _WIN32 #ifdef SOFTIMAGE #ifndef BROKEN void _sliidi( void ) { } void _sliien( char *a ) { } void _sliiwr( int a, int b, char *c ) { } void _sliird( int a, int b, char *c ) { } #endif #endif #endif #ifndef _WIN32 //void _sliidi (void) {} //void _sliien(char *a) {} //void _sliiwr(int a, int b, char *c) {} //void _sliird(int a, int b, char *c) {} #endif static void reset_dynamics( void ); //#include "data.h" ///#include "zor.c" #define font9 19 #define font10 20 #define font30 60 #include //#include //#include "gluaux.c" #define lightwave 1 #include static void reset_mmode( void ); //#define wavefront 1 static void DRAW_PERFORMANCE_GROUP_BUTTONS( ); //#include "valuators.cpp" static VERT vxmp( Matrix m, VERT vv ); static void init_noise( void ) { int x, y, z; float rr; GLOBS *gs,ggl; //gs = >hreads[0]; gs = &ggl; init_thread(gs); gs->random_seed_offset=0; if( noise_been_done == 0 ) { init_tiles( ); sculpt.z = 170.0; init_geomWF( &Guv ); #ifdef EXTERNAL_COLLISION // Gsurface_collide[0] = 1; // Gsurface_collide[1] = 1; // Gsurface_collide[2] = 1; // Gsurface_collide[3] = 1; // Gsurface_collide[4] = 1; #endif for( rr = 0; rr < ( float ) 6.283; rr += ( float ) ( 6.283 / 628.0f ) ) { COST[( int ) ( rr * 100.0f )] = cos( rr ); SINT[( int ) ( rr * 100.0f )] = sin( rr ); } dither_seed = 0; rand59_seed = 0; rand69_seed = 0; rand48_seed = 0; gseed = 0; sgenrand_been_seeded = 0; MTJsrand( 0,gs ); for( x = 0; x < 1399; x++ ) { int xx; float dd; campass[x].x = ( float ) ( ( ( float ) MTdrand98( gs ) ) - .5 ) * .78f; for( xx = 0; xx < ( int ) ( MTdrand98( gs ) * 30.0f ); xx++ ) dd = MTdrand98( gs ); campass[x].y = ( float ) ( ( ( float ) MTdrand98( gs ) ) - .5 ) * .78f; } // campass[0].x= -2.0f; // campass[0].y=0.0f; campass[0].x = 0; campass[0].y = 0; for( x = 0; x < 20; x++ ) for( y = 0; y < 20; y++ ) for( z = 0; z < 20; z++ ) { noise[x][y][z] = ( float ) MTdrand98( gs ); } // noise[x][y][z]=(float)((float)rand()/(float)RAND_MAX); // for (y=0;y<20;y++) // for (z=0;z<20;z++) // noise[0][y][z]=noise[19][y][z]; // for (x=0;y<20;y++) // for (z=0;z<20;z++) // noise[x][0][z]=noise[x][19][z]; // for (x=0;y<20;y++) /// for (y=0;z<20;z++) // noise[x][y][0]=noise[x][y][19]; // for( x = 0; x < 115123; x++ ) // rtable[x] = ( float ) MTdrand98( gs ); // rtable[x]=(float)rand()/(float)RAND_MAX; noise_been_done = 1; } } static float drand59( void ) { float ret; // ret = rtable[rand59_seed]; rand59_seed++; if( rand59_seed > 115123 ) rand59_seed = 0; // ret=(float)rand()/(float)RAND_MAX; return ( ret ); } static float drand69( void ) { float ret; // ret = rtable[rand69_seed]; rand69_seed++; if( rand69_seed > 115123 ) rand69_seed = 0; // ret=(float)rand()/(float)RAND_MAX; return ( ret ); } static float drand49( void ) { float ret; rand48_seed++; if( rand48_seed > 115123 ) rand48_seed = 0; // ret = rtable[rand48_seed]; // ret=drand98(); return ( ret ); } //#ifdef crap static double drand98( void ) { double ret; // ret = MTdrand98( >hreads[0] ); ret = MOdrand( >hreads[0] ); return ( ret ); } //#endif double MOdrand( GLOBS * gs ); void MOsrand (uint32 seed, GLOBS * gs); #if defined(_WIN32) && (_MSC_VER < 1400) //#ifndef NEWRAND void MOsrand (uint32 seed, GLOBS * gs) { int i; uint32 s = seed; // make random numbers and put them into the buffer for (i=0; i<5; i++) { s = s * 29943829 - 1; gs->x[i] = s * (1./(65536.*65536.));} // randomize some more for (i=0; i<3; i++) MOdrand(gs);} double MOdrand( GLOBS * gs ) { long double c; c = (long double)2111111111.0 * gs->x[3]; c += 1492.0 * (gs->x[3] = gs->x[2]); c+= 1776.0 * (gs->x[2] = gs->x[1]); c += 5115.0 * (gs->x[1] = gs->x[0]) + gs->x[4]; gs->x[4] = floorl(c); gs->x[0] = c - gs->x[4]; gs->x[4] = gs->x[4] * (1./(65536.*65536.)); return gs->x[0]; } #else void MOsrand (uint32 seed, GLOBS* gs) { int i; unsigned int s = seed; for (i=0; i<5; i++) { s = s * 29943829 - 1; gs->x[i] = s; } for (i=0; i<3; i++) MOdrand(gs); } double MOdrand(GLOBS* gs) { static const double maxDivisor = 1.0L / (65536.0L * 65536.0L); unsigned long long S; S = 2111111111LL * gs->x[3] + 1492LL * gs->x[2] + 1776LL * gs->x[1] + 5115LL * gs->x[0] + gs->x[4]; gs->x[3] = gs->x[2]; gs->x[2] = gs->x[1]; gs->x[1] = gs->x[0]; gs->x[0] = S & 0xffffffffLL; gs->x[4] = S >> 32; return maxDivisor * (double)gs->x[0]; } #endif double MTdrand98( GLOBS * gs ) { // double ret; unsigned long q, MX; // unsigned long s; double ret; // MX=2<<12; // MX-=1; //MX=32767; //MX=19932767; MX = 8388607; { // q = MTgenrand( gs ) & ( ( unsigned long ) ( MX ) ); // ret = ( ( double ) q / ( double ) ( MX ) ); ret=MOdrand(gs); // gs->jrandseed++; //GLseed++; // s=GLseed; // s = s<<13 ^ s; // ret=1.0f-((s*(s*s*15731+789221)+1376312589)&0x7fffffff)/1073741824.0; // if (ret<0.0f) ret=0.0f; // if (ret>=1.0f) ret=.999999999f; } return ( ret ); } static void Jsrand( unsigned long seed ) { int x; float q; MTJsrand( seed, >hreads[0] ); } static void MTJsrand( unsigned long seed, GLOBS * gs ) { int x; float q; seed++; first_rand_gen = 0; // fprintf (stdout,"rand offset = %d\n",gs->random_seed_offset);fflush(stdout); // jrandseed = seed; gs->lastSeed=seed; // MTsgenrand( seed, gs ); seed+=(unsigned long)gs->random_seed_offset*(unsigned long)11000; MOsrand( seed, gs ); //GLseed=seed; // srand((unsigned long)seed); } static void JsrandFAST( unsigned long seed ) { float a; int x; rand98_seed = seed; for( x = 0; x < 10 * drand98( ); x++ ) a = drand98( ); } static double drand98FAST( void ) { long unsigned int hi, lo; static unsigned long MX = 0x7FFFFFFF; lo = 16807 * ( unsigned long ) ( rand98_seed & 0xFFFF ); hi = 16807 * ( unsigned long ) ( rand98_seed >> 16 ); lo += ( hi & 0x7FFF ) << 16; if( lo > 2147483647 ) { lo &= 2147483647; ++lo; } lo += hi >> 15; if( lo > 2147483647 ) { lo &= 2147483647; ++lo; } //lo = (lo & 0x7FFF); rand98_seed = lo + 1; return ( ( ( ( double ) lo ) / ( ( double ) 2147483647 ) ) ); //return(( ((double)lo)/((double)2147483647) )); } static float baddrand50( int offset ) { float ret; ret = drand98( ); return ( ret ); } static float drand50( int offset ) { float ret; int qq; // qq=rand48_seed+offset; // qq=qq % 115000; // ret=rtable[qq]; // rand48_seed++; // if (rand48_seed>115123) rand48_seed=0; ret = ( float ) drand98( ); return ( ret ); } #ifdef DLL static VERT RMAN_BOUND1, RMAN_BOUND2; // bounding box for renderman static int VOXEL_DIVS = 10; static reset_rmanbound( ) { int x, y, z; RMAN_BOUND1.x = 100000; RMAN_BOUND1.y = 100000; RMAN_BOUND1.z = 100000; RMAN_BOUND2.x = -100000; RMAN_BOUND2.y = -100000; RMAN_BOUND2.z = -100000; // clear out the voxels } static void color_a_hair( BASEHAIR * ); static void RM_MAKE_OBJECT( ) { int x, y; int clone = 0; BASEHAIR hh; mkbounds( ); weight_polys( ); texture_bounds( ); //printf ("SubdivisionMesh \"catmull-clark\" [ \n"); printf( "PointsPolygons [ \n" ); for( x = 0; x < Dtotalfaces; x++ ) { printf( "%d ", ( Dface_end[x] - Dface_start[x] ) ); } printf( "]\n" ); // nverts (per face) printf( " [\n" ); for( x = 0; x < Dtotalfaces; x++ ) { for( y = Dface_start[x]; y < Dface_end[x]; y++ ) printf( "%d ", Dfacelist[y] ); } printf( "]\n" ); // vertids (facelist) printf( "\"P\" [ " ); for( x = 0; x < Dtotalverts; x++ ) { printf( "%f %f %f\n", Dv[x].x, Dv[x].y, Dv[x].z ); } printf( "]\n" ); printf( "\"N\" [ " ); for( x = 0; x < Dtotalverts; x++ ) { int g; int xx; BASEHAIR h; printf( "%f %f %f\n", Dvn[x].x, Dvn[x].y, Dvn[x].z ); } printf( "]\n" ); printf( "\"Cs\" [ " ); for( x = 0; x < Dtotalverts; x++ ) { int g; int xx; g = x; for( xx = 0; xx < 15; xx++ ) hh.hv[xx] = Dv[g]; hh.mtl = Dvertgroup[x]; if( ( hh.mtl != beard ) || ( hh.mtl != head ) || ( hh.mtl != eyebrow ) || ( hh.mtl != eyelash ) ) { color_a_hair( &hh ); } else { hh.color[0].x = .3; hh.color[0].y = .3; hh.color[0].z = .3; } printf( "%f %f %f\n", hh.color[0].x, hh.color[0].y, hh.color[0].z ); } printf( "]\n" ); } #endif static float distance( VERT a, VERT b ); // mkbounds(); //reset_faces(); //checkforzero(); //make_normals(); //texture_bounds(); //weight_polys(); // reset_faces(); static void prgen_hair( int seed, int segs1, int segs2, int segs3, int segs4, int segs5 ) { int x; int y; int slg = 1; int segs[5]; RENDERHAIR h; WFTYPE wf; CURVEINFO ci; int a; segs[0] = segs1; segs[1] = segs2; segs[2] = segs3; segs[3] = segs4; segs[4] = segs5; init_geomWF( &wf ); printf( "Curves \"linear\" [" ); for( slg = 0; slg < 5; slg++ ) for( x = 0; x < LOCAL_CNT[slg]; x++ ) { MAYAmake_a_curve( seed, slg, x, segs[slg], &wf, &ci ); if( wf.totalverts > 0 ) printf( " %d\n", ( int ) ( wf.totalverts ) ); } printf( "] \"nonperiodic\" \n\"P\"\n [\n" ); for( slg = 0; slg < 5; slg++ ) for( x = 0; x < LOCAL_CNT[slg]; x++ ) { MAYAmake_a_curve( seed, slg, x, segs[slg], &wf, &ci ); for( a = 0; a < wf.totalverts; a++ ) { printf( "%f %f %f\n", wf.v[a].x, wf.v[a].y, wf.v[a].z ); } printf( "\n" ); } printf( "]\n" ); printf( "\"width\" [\n" ); for( slg = 0; slg < 5; slg++ ) for( x = 0; x < LOCAL_CNT[slg]; x++ ) { MAYAmake_a_curve( seed, slg, x, segs[slg], &wf, &ci ); for( a = 0; a < wf.totalverts; a++ ) { float segments; segments = ( float ) segs[slg]; printf( "%f\n", ci.baserad * ( 1.0 / segments ) * ( float ) ( segments - a ) ); } printf( "\n" ); } printf( "]\n " ); printf( "\"Cs\" [\n" ); for( slg = 0; slg < 5; slg++ ) for( x = 0; x < LOCAL_CNT[slg]; x++ ) { MAYAmake_a_curve( seed, slg, x, segs[slg], &wf, &ci ); for( a = 0; a < wf.totalverts; a++ ) { printf( "%f %f %f\n", wf.color[a].x, wf.color[a].y, wf.color[a].z ); } } printf( "]\n" ); } #ifdef PRMAN //#include //#include static void init_noise( void ); #include #include int slcheck( void ); static main( int argc, char *argv[] ) { int x; MEMFILE restmem, statemem; char tmp[255]; char buf[256]; FILE *fp = NULL; init_noise( ); init_MEMFILE( &restmem, 0 ); init_MEMFILE( &statemem, 0 ); // if (argc==11) // while (gets(buf) != NULL) { int segs1, segs2, segs3, segs4, segs5; int seed; init_noise( ); MAYAread_hairDISK( "for_timm.hair", &restmem, &statemem ); MAYAset_state( &restmem, &statemem, .5, "gshep0015.stat", "gshep0016.stat" ); // MAYAread_hairDISK(argv[1],&restmem,&statemem); // MAYAset_state(&restmem,&statemem,atof(argv[4]),argv[2],argv[3]); // seed=atoi(argv[5]); // segs1=atoi(argv[6]); // segs2=atoi(argv[7]); // segs3=atoi(argv[8]); // segs4=atoi(argv[9]); // segs5=atoi(argv[10]); seed = 0; segs1 = 10; segs2 = 10; segs3 = 10; segs4 = 10; segs5 = 10; prgen_hair( seed, segs1, segs2, segs3, segs4, segs5 ); // make the 2nd geom for MB // we could printf the 2nd motion block begin here if necessary // create the 2nd state (have to add some more parms): // MAYAset_state(&restmem,&statemem,atof(argv[4]),argv[2],argv[3]); // prgen_hair(seed,segs1,segs2,segs3,segs4,segs5); free_MEMFILE( &restmem ); free_MEMFILE( &statemem ); } if( 0 == 1 ) if( argc != 11 ) { printf( "version = %s\n", version_info ); printf( "usage: SHAVEcurvegen.exe [hairfile statfileA statefileB interp seed segsHAIR segsBEARD segsEYEBROW segsEYELASH segsSPLINE]\n" ); printf( " hairfile - the rest state hairfile for your critter\n" ); printf( " statfileA - a frame state for your critter in motion\n" ); printf( " statfileB - another frame state for your critter in motion\n" ); printf( " interp - the interpolation between stateA and stateB (0.0f-1.0f)\n" ); printf( " seed - a random seed offset which gets modulused by 'passes' in the shave interface\n" ); printf( " segsHAIR - number of segments in the curve for the HAIR group\n" ); printf( " segsBEARD - number of segments in the curve for the BEARD group\n" ); printf( " segsEYEBROW - number of segments in the curve for the EYEBROW group\n" ); printf( " segsEYELASH - number of segments in the curve for the EYELASH group\n" ); printf( " segsSPLINE - number of segments in the curve for the SPLINE group\n" ); } printf( "\377" ); } #endif