diff options
Diffstat (limited to 'mayaPlug/shavePack2TexCmd.cpp')
| -rw-r--r-- | mayaPlug/shavePack2TexCmd.cpp | 334 |
1 files changed, 334 insertions, 0 deletions
diff --git a/mayaPlug/shavePack2TexCmd.cpp b/mayaPlug/shavePack2TexCmd.cpp new file mode 100644 index 0000000..b9def1a --- /dev/null +++ b/mayaPlug/shavePack2TexCmd.cpp @@ -0,0 +1,334 @@ +// Shave and a Haircut +// (c) 2019 Epic Games +// US Patent 6720962 + +/********************************************************************** + *< + FILE: shavePack2TexCmd.cpp + + DESCRIPTION: command for packing hair data to image file + + HISTORY: created 23-04-2013 + + *> + **********************************************************************/ + +#include "shavePack2TexCmd.h" +#include "shaveHairShape.h" +#include "shaveAPI.h" +#include "shaveRender.h" + +#include <maya/MDagPath.h> +#include <maya/MFnDependencyNode.h> +#include <maya/MDGModifier.h> +#include <maya/MArgDatabase.h> +#include <maya/MPlugArray.h> +#include <maya/MDagModifier.h> +#include <maya/MSelectionList.h> +#include <maya/MFnRenderLayer.h> +#include <maya/MItDependencyNodes.h> + + + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ +| Command | +/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + +MString shavePack2TexCmd::cmd = "shavePack2Tex"; + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ +| Flags | +/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + +char* shavePack2TexCmd::sf_file = "f"; + +char* shavePack2TexCmd::lf_file = "file"; + +char* shavePack2TexCmd::sf_hair = "h"; + +char* shavePack2TexCmd::lf_hair = "hair"; + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ +| Methods | +/~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + +MStatus shavePack2TexCmd::doIt(const MArgList &maList) +{ + MStatus stat; + + MArgDatabase parser(syntax(),maList,&stat); + if(stat != MStatus::kSuccess) + { + MGlobal::displayError("shavePack2TexCmd: can not parse arguments."); + return stat; + } + + if(parser.isFlagSet(sf_file) && + parser.isFlagSet(sf_hair)) + { + MString file; + MString hair; + if(parser.getFlagArgument(sf_file,0,file) != MStatus::kSuccess) + { + MGlobal::displayError("shavePack2TexCmd: can not get 'file' argument."); + return MStatus::kFailure; + } + MStringArray fparts; + if(file.split('.',fparts) != MStatus::kSuccess || fparts.length() < 2) + { + MGlobal::displayError(MString("shavePack2TexCmd: can not get file extention from ") + file); + return MStatus::kFailure; + } + if(fparts[1] != "tga") + { + MGlobal::displayWarning("shavePack2TexCmd: you need 32bpp format without compression .tga"); + return MStatus::kFailure; + } + if(parser.getFlagArgument(sf_hair,0,hair) != MStatus::kSuccess) + { + MGlobal::displayError("shavePack2TexCmd: can not get 'hair' argument."); + return MStatus::kFailure; + } + MObject node; + if(!findNodeByName(hair,node)) + { + MGlobal::displayError(MString("shavePack2TexCmd: can not find ") + hair + " node"); + return MStatus::kFailure; + } + MFnDependencyNode dFn(node); + if(dFn.typeId() != shaveHairShape::id) + { + MGlobal::displayError(MString("shavePack2TexCmd: the node ") + hair + " is not a shaveHairShape"); + return MStatus::kFailure; + } + MImage img; + if(!copyToImage(node,img)) + { + MGlobal::displayError("shavePack2TexCmd: can not pack to image."); + return MStatus::kFailure; + } + + MString mdir; + MGlobal::executeCommand("internalVar -userWorkspaceDir",mdir); + + MString out = mdir+file; + MGlobal::displayInfo(MString("shavePack2TexCmd: saving file ") + out ); + + if(img.writeToFile(out,fparts[1]) != MStatus::kSuccess) + { + MGlobal::displayError(MString("shavePack2TexCmd: can not write ") + out ); + return MStatus::kFailure; + } + return MStatus::kSuccess; + } + else + { + MGlobal::displayError("shavePack2TexCmd: you should specify 'file' and 'hair' flags."); + return MStatus::kFailure; + } +} + +MSyntax shavePack2TexCmd::newSyntax() +{ + MSyntax syn; + + syn.addFlag(sf_file, lf_file, MSyntax::kString); + syn.addFlag(sf_hair, lf_hair, MSyntax::kString); + + return syn; +} +#define SIMPLE_PACK +static void i2c(unsigned char* c, unsigned int i) +{ +#ifdef SIMPLE_PACK + memcpy(c,&i,4); +#else + char b[4] = {0,0,0,0}; + b[3] = i/1000000; + i -= b[3]*1000000; + b[2] = i/10000; + i -= b[2]*10000; + b[1] = i/100; + i -= b[1]*100; + b[0] = i; + memcpy(c,b,4); +#endif +} +static void f2c(unsigned char* c, float f) +{ +#ifdef SIMPLE_PACK + memcpy(c,&f,4); +#else + char sign = f >= 0.0f ? 1 : 0; + f = fabs(f); + float af = floor(f); + float df = f - af; + if(df < 0.01f) + df = 0.0f; + + //int d = f * pow(10.0f,7) - a * pow(10.0f,7); + //while(d >= 100) + // d /= 10; + + int a = (int)af; + int d = (int)(df*100.0f); + + char b[4] = {0,0,0,0}; + b[3]=(char)(a/256); + b[2]=a%256; + b[1]=d; + b[0]=sign; + memcpy(c,b,4); +#endif +} + +bool shavePack2TexCmd::copyToImage(MObject node, MImage& image) const +{ + //MObjectArray nodes; + //nodes.append(node); + + //crap, unresolved!! + //shaveAPI::HairInfo h; + //shaveAPI::exportHair(nodes, &h); + + //MFnDependencyNode dFn(node); + //shaveHairShape* hairShape = (shaveHairShape*)dFn.userNode(); + //SHAVENODE* hairNode = hairShape->getHairNode(); + //hairShape->setStackIndex(0); + //SHAVEclear_stack(); + //SHAVEadd_hairOPEN2(hairNode, 0); + + MObjectArray nodes; + nodes.append(node); + shaveRender::buildHairStack(nodes, shaveConstant::kShutterBoth); + + + HAIRTYPE h; + SHAVEinit_hairtype(&h); + SHAVEexport_hairtype(&h); + +// if(h.numHairs == 0 || h.numVertices == 0 || h.numHairVertices == 0) +// return false; + + if(h.totalfaces == 0 || h.totalverts == 0 || h.totalfverts == 0) + { + MGlobal::displayError("shavePack2TexCmd: hairtype is empty."); + return false; + } + + struct header + { + unsigned char num_hairs[4]; + unsigned char num_knots[4]; + }; + struct hair + { + unsigned char start_vert[4]; + unsigned char tip_radi[4]; + unsigned char root_radi[4]; + + unsigned char root_color_r[4]; + unsigned char root_color_g[4]; + unsigned char root_color_b[4]; + + unsigned char tip_color_r[4]; + unsigned char tip_color_g[4]; + unsigned char tip_color_b[4]; + }; + struct vertex + { + unsigned char x[4]; + unsigned char y[4]; + unsigned char z[4]; + }; + //[header][hairs array][verts arra] + //int numknots = h.hairEndIndices[0] - h.hairStartIndices[0]; + int numknots = h.face_end[0] - h.face_start[0]; + int numhairs = h.totalfaces; + + header he; + //i2c(he.num_hairs,h.numHairs); + i2c(he.num_hairs,h.totalfaces); + + i2c(he.num_knots,numknots); + + + hair* har = (hair*) malloc(numhairs*sizeof(hair)); + vertex* var = (vertex*) malloc(numhairs*numknots*sizeof(vertex)); + for(int i = 0; i < numhairs; i++) + { + hair& hh = har[i]; + i2c(hh.start_vert,i*numknots); + + //f2c(hh.tip_radi,h.tipRadii[i]); + //f2c(hh.root_radi,h.rootRadii[i]); + + f2c(hh.tip_radi,h.radiustip[i]); + f2c(hh.root_radi,h.radiusroot[i]); + + + //f2c(hh.root_color_r,h.rootColors[i].r); + //f2c(hh.root_color_g,h.rootColors[i].g); + //f2c(hh.root_color_b,h.rootColors[i].b); + + f2c(hh.root_color_r,h.colorroot[i].x); + f2c(hh.root_color_g,h.colorroot[i].y); + f2c(hh.root_color_b,h.colorroot[i].z); + + + //f2c(hh.tip_color_r,h.tipColors[i].r); + //f2c(hh.tip_color_g,h.tipColors[i].g); + //f2c(hh.tip_color_b,h.tipColors[i].b); + + f2c(hh.tip_color_r,h.colortip[i].x); + f2c(hh.tip_color_g,h.colortip[i].y); + f2c(hh.tip_color_b,h.colortip[i].z); + + + for(int k = 0; k < numknots; k++) + { + //int vi = h.hairStartIndices[i] + k; + int vi = h.face_start[i] + k; + + vertex& vv = var[i*numknots + k]; + //f2c(vv.x, h.vertices[vi].x); + //f2c(vv.y, h.vertices[vi].y); + //f2c(vv.z, h.vertices[vi].z); + + f2c(vv.x, h.v[vi].x); + f2c(vv.y, h.v[vi].y); + f2c(vv.z, h.v[vi].z); + } + } + int npix = (sizeof(header) + numhairs*sizeof(hair) +numhairs*numknots*sizeof(vertex))/4; + int W = 1024; + int H = 1 + npix/W; + + image.create(W,H,4); + unsigned char* pix = image.pixels(); + memcpy(pix,&he,sizeof(header)); + memcpy(&pix[sizeof(header)],har,numhairs*sizeof(hair)); + memcpy(&pix[sizeof(header)+ numhairs*sizeof(hair)],var,numhairs*numknots*sizeof(vertex)); + free(har); + free(var); + return true; +} + +bool shavePack2TexCmd::findNodeByName(const MString& name, MObject& thenode) const +{ + if(name == "") + return false; + + MItDependencyNodes iter; + for (; !iter.isDone(); iter.next()) + { + MObject node = iter.item(); + MFnDependencyNode dFn(node); + if(dFn.name() == name) + { + thenode = node; + return true; + } + } + return false; +} |