aboutsummaryrefslogtreecommitdiff
path: root/mayaPlug/shavePack2TexCmd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mayaPlug/shavePack2TexCmd.cpp')
-rw-r--r--mayaPlug/shavePack2TexCmd.cpp334
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;
+}