// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 // this is the alternate include for the dual memfile API // it's a lower level version of the shaveSDK, and a little harder to use // #include // version 1.4 r13 typedef struct { float x,y,z; } VERT; // stucture for a vertex // simple data type for holding geometry typedef struct { int totalverts; int totalfaces; int totalfverts; int *facelist; // list of face verts int *face_start; // face refferenced index into facelist int *face_end; // face refferenced index into facelist VERT *color; // vert refferenced color VERT *v; // vert refferenced vertex position VERT *uv; // vert refferenced uv info (x,y) int *index; // coming soon for subdivs // int *pid; // facevert refferenced, same size as *facelist // VERT *bary; // facevert refferenced, same size as *facelist // pid reffers to the original face (after triangulaiton) // bary reffers to vert weights on that original triangle } WFTYPE; typedef struct { WFTYPE original_mesh; WFTYPE Toriginal_mesh; // pid's reffer to this one WFTYPE Smesh; // subdivided mesh WFTYPE TSmesh; // subdivided/triangulated mesh } SUBDIVTYPE; // settings parameters for hair groups // [0]=splines // [1]=hair // [2]=beard // [3]=eyebrows // [4]=eyelashes // this type contains general shave engine info typedef struct { int haircount[5]; // number of hairs to be generated for this group int passes[5]; // number of passes to generated float slider_val[41][6]; // slider settings char slider_lable[41][6][50]; // slider lables int painted[41][6]; // 1=has weight painting 0= no weight painting int total_guides; // total guide hairs int instancing_status; } SHAVEPARMS; // opaque multi-use data type typedef struct { long size; long pos; char *data; long ID; int time; } MEMFILE; // this is used for keeping track of which engine is // active. it's originally set with init_MEMFILE long MAYAquery_shave_ID(void); // this returns a string with the current version info on the lib char *MAYAquery_version(void); // this purges the instance when you're ready to shut things down void clear_shave_engine(void); void MAYArefresh(char *objfilename, MEMFILE *,MEMFILE *, SHAVEPARMS *); // params for MATArefresh // char * - this is a filename/path to a wf obj temp file that you have put // to disk for hair creation // MEMFILE * - this is the opaque data that is returned with an initial growth // MEMFILE * - this is the opaque data that will be used for velocity info // SHAVEPARMS * - this is the settings info that's returned for haircounts/passes // if you call it with objfile set to NULL then everything else become INPUT parms void MAYAwrite_hairDISK(char *hairfilename); // params for MAYAwrite_hairDISK // char * - filename/path for hairfile // this function writes out the current shave memory to a hair file void MAYAread_hairDISK(char *hairfilename, MEMFILE *,MEMFILE *); // params for MAYAread_hairDISK // char * - filename/path for hairfile // MEMFILE * - opaque data type to read node data into // MEMFILE * - opaque data type to read nodestate data into void MAYAxform(WFTYPE *objfile,MEMFILE *,MEMFILE *,int run_dyn, char *stat); // params for MAYAxform // WFTYPE * - position of the skin verts at the current position // MEMFILE * - opaque data for the hair style information // always pass this the rest position // MEMFILE * - opaque data for the velocity information // int - run_dyn flag. Set to // 0== just transform hair stiffly // -1== reset dynamics, use this for the first dyanmics call // 1== run the dyanmics using the current velocity info // 2== don't run dynamics or xform. Just grab positional info from // stat files. Meaning, you've already run the simulation // char * - statfile name (including 4pad and extension - ie afile0001.stat) // this is not a tempfile. You should be storing it in a way that // you can recall it specific to the object void MAYAmake_a_hair(int, int , int , int ,WFTYPE *); // this function will make a hair (or an instance) out of polygons // params for MAYAmake_a_hair // int - pass number // int - hair group (0-5) // int - hair index // int - number of hair segs to generate // WFTYPE * - holder for strand(s) - don't malloc, make sure the .totalverts member // is set to 0 on first use void MAYAset_state(MEMFILE *,MEMFILE *, float uu,char *stat1,char *stat2); // params for MAYAset_state // MEMFILE * - opaque data for the hair style information (read only) // always pass this a copy of the rest position // MEMFILE * - opaque data for the hair state information // pass this the MEMFILE malloced by refresh, or a copy. ***This function writes into // this structure **** // float - interpolation bais control // char * - statfile name (including 4pad and extension - ie afile0001.stat) // this is not a tempfile. You should be storing it in a way that // you can recall it specific to the object. // char * - statfile name (including 4pad and extension - ie afile0001.stat) // this is not a tempfile. You should be storing it in a way that // you can recall it specific to the object. // // this function works like xform, except with two statfiles and a floating point // bias. It's used for recalling a fractional frame number after dynamics have been // run void MAYAgetobj(char *name, WFTYPE *wfdata); // params for MAYAgetobj // char * - file name (including path if any) // WFTYPE * - data structure containing unsurfaced polys // don't malloc, just set the .totalverts member to 0 on first // use // this function will probably not get used in the app, but it is here // for the example, since we are starting with an obj file. Normally you // you fill in the WFTYPE data members and pass them into MAYAxform yourself #ifdef _WIN32 #include // this is needed only for the Sleep statement we are using in this example // otherwise, just include the following 3 #endif #ifndef _WIN32 #include #include #include #endif // // // Shave Render API (under construction) // // void MAYAgetobj(char *name, WFTYPE *wfdata); // get an objfile from disk and alloc/create WFTYPE from it typedef float Matrix[4][4]; typedef struct { int Tpid; // face ID (after triangulation) int UTpid; // faceID (with no triangulation) int pntid[3]; // point IDs float wgt[3]; // point weights float baserad; // the base radius float tiprad; // the tip radius Matrix rest2zero[15]; // matricies for 15 points on the guides Matrix zero2world[15]; float u,v; // interpolated uv coords VERT norm; // interpolated surface normal float diff,spec,kspec,shad; // some render params int killme; // some times empty hairs will get returned (for point count consistancy) // because they've been 'killed' by densemaps, cutmaps, etc - this will let // you know: killme=1 } CURVEINFO; // this stucture gets returned from make_a_curve, and make_a_curveROOT and contains // all kinds of non vertex info. void MAYAmake_a_curve(int current_samp,int slg, int hairnum ,int segs, WFTYPE *, CURVEINFO *); // generally used to make a hair void MAYAmake_a_curveROOT(int current_samp,int slg, int hairnum , WFTYPE *, CURVEINFO *); // this is a faster version of the above that you can use when you just need the general info in 'curveinfo' // and the first point from the curve in WFTYPE void MAYAclear_scene(void); // this purges out all the lights and camera stuff you've set up for renders // also clears the stack of shave instances and skin objects // just run this after rendering void MAYAmake_view_matrix(Matrix vm,VERT vv, VERT nn,VERT wpos,float fov); // used for seting up a view matrix int MAYAadd_light(float r,float g,float b,Matrix vm,VERT wpos, int xres, int yres, float aspect,float fov, int trace, int type); // add a lightsource void MAYAset_cameraOPEN(Matrix vm,VERT wpos, int xres, int yres, float aspect,float fov); // sets the camera for the shutter open void MAYAset_cameraCLOSE(Matrix vm,VERT wpos); // sets the camera for the shutter close void init_MEMFILE(MEMFILE *mf,long ID); // new ID // this is used to initialize a MEMFILE data structure // give it a unique ID # for later tracking void free_MEMFILE(MEMFILE *mf); // this frees a MEMFILE structure void copy_MEMFILE(MEMFILE *out,MEMFILE *in); // this copys a memfile structure for you, you'll probably want to set the ID // member yourself on the copy to some unique value void alloc_MEMFILE(MEMFILE *mf); // this allocates a MEMFILE, given the size member's setting void alloc_geomWF(WFTYPE *geom); // this allocates a WFTYPE given the totalverts,totalfaces,totalfverts members void init_geomWF(WFTYPE *geom); // this initializes a WFTYPE structure void free_geomWF(WFTYPE *geom); // this frees a WFTYPE structure void free_MEMFILE(MEMFILE *mf); // this frees a MEMFILE structure void MAYAadd_hairOPEN(MEMFILE *hairdataREST,MEMFILE *hairstateOPEN); // this adds a hairfile for rendering at shutter open // hairstateOPEN is a -state- MEMFILE void MAYAadd_hairCLOSE(MEMFILE *hairstateCLOSE); // this adds a hairfile for rendering at shutter close // hairstateCLOSE is a -state- MEMFILE void MAYArender_frame(WFTYPE *geom_open, WFTYPE *geom_close, int antialiasing, int mbsampling,unsigned char *image,float *zbuff); // render the frame. the WFTYPES are occlusion (skin) geometry of the scene void MAYAwrite_targa(char filename[255],short width,short height,unsigned char *image); // this is a helper function to write a buffer out to a targa32 file void MAYAfetch_parms(SHAVEPARMS *shavep); // this is used to see the shave engine's current params void MAYAset_parms(SHAVEPARMS *shavep); // this function injects shave parameters into shave memory void MAYAxplant(char *xfile); // transplant hairstile onto a new wavefront objfile. xfile is the filename void MAYAmake_a_spline(int current_samp,int slg, int hairnum ,int segs, WFTYPE *); // obsolete void MAYAxformNOSTAT(WFTYPE *objfile,MEMFILE *,MEMFILE *,int run_dyn); // similar to xform, but no statfiles are used. void MAYAfetch_node(MEMFILE *node,MEMFILE *node_state,SHAVEPARMS *shavep); // this function will fetch info from shave memory // pass NULL into the structures that you -dont- want to fill void MAYAdump_stats(char *statname); // this will dump shave's current 'hairstate' to a '.stat' file void MAYAset_gravity_vector(VERT); // obsolete extern void MAYAdo_external_forces(int); // 1 or 0 int MAYAinsert_uv_coords(WFTYPE *); // returns 1 if success - u and v are stored in x and y void MAYAflush_state( MEMFILE *node,MEMFILE *state); // flushes the engine given the resetMEM and stateMEME as inputs (no modification on the MEMS) // this is used to set the shave engine to whatever's in the MEMFILES void MAYAset_stateMEM( MEMFILE *node,MEMFILE *state,float uu,MEMFILE *stat1,MEMFILE *stat2); // flushes the engine with rest state, and interps the two statemems. // Interpolated mem returned in 'state'