// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 /********************************************************************** *< FILE: shaveVrayNode.cpp -- implementation file DESCRIPTION: Maya node HISTORY: created 29-03-2010 *> **********************************************************************/ #include "shaveVrayNode.h" #include "shaveRender.h" #include "shaveGlobals.h" #include "shaveVrayRenderer.h" #include "shaveVraySharedFunctions.h" #include "shaveVrayExporter.h" //#include "shaveVrayDesc.h" //#include "shaveVrayPlugin.h" //#include "shaveVrayCallbacks.h" #include #include #include #include #include #ifdef USE_VRAY #include #include #ifdef _WIN32 #define fileno _fileno #define fstat _fstat #define snprintf _snprintf typedef struct _stat StatType; #else #include #include typedef struct stat StatType; #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ | V-Ray export impl | /~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ typedef shaveVrayExporter *(*TFnNewShaveVrayExporter) (); typedef void (*TFnDeleteShaveVrayExporter) (shaveVrayExporter *); // Pointer to function implementing the actual plugin creation static TFnNewShaveVrayExporter newShaveVrayExporter=0; static TFnDeleteShaveVrayExporter deleteShaveVrayExporter=0; // If load failed once already static bool loadShaveVRayExportImplFailed=false; static bool startsWith(const MString &str, const char *beg) { unsigned begLength = unsigned(strlen(beg)); if (begLength > str.length()) { return false; } MString pref = str.substring(0, begLength-1); return pref == beg; } // Load required dll and get function to create V-Ray plugin static int loadShaveVRayExportImpl() { if (loadShaveVRayExportImplFailed) { return false; } if (newShaveVrayExporter && deleteShaveVrayExporter) { return true; } MString dllPath; MStatus st; st=MGlobal::executeCommand("dirname(`pluginInfo -q -p shaveNode`)", dllPath); if (st.error()) { st.perror("Get shaveNode location"); loadShaveVRayExportImplFailed=true; return false; } MString vrayVersion; st=MGlobal::executeCommand("vray version", vrayVersion); if (st.error()) { st.perror("Get V-Ray version"); loadShaveVRayExportImplFailed=true; return false; } #if defined(_WIN32) dllPath+="/vray/ShaveVray"; #elif defined(__linux__) || defined(OSMac_) dllPath+="/vray/libShaveVray"; #endif if (startsWith(vrayVersion, "4.")) { dllPath+="40"; } else if (startsWith(vrayVersion, "3.")) { dllPath+="36"; } dllPath+="Exporter"; #if defined(_WIN32) dllPath+=".dll"; HMODULE hDll; # if defined(_UNICODE) hDll=LoadLibraryW(dllPath.asWChar()); # else hDll=LoadLibraryA(dllPath.asChar()); # endif // UNICODE if (!hDll) { int errCode=GetLastError(); char *msgbuf = NULL; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPSTR) &msgbuf, 0, NULL ); const int errBufLen=512; char *errBuf=(char*)alloca(errBufLen); errBuf[errBufLen]='\0'; snprintf(errBuf, errBufLen, "LoadLibrary(%s) failed (%i): %s", dllPath.asChar(), errCode, msgbuf); LocalFree(msgbuf); MGlobal::displayError(errBuf); loadShaveVRayExportImplFailed=true; return false; } newShaveVrayExporter=(TFnNewShaveVrayExporter)GetProcAddress(hDll, "newShaveVrayExporter"); deleteShaveVrayExporter=(TFnDeleteShaveVrayExporter)GetProcAddress(hDll, "deleteShaveVrayExporter"); #elif defined(__linux__) || defined(OSMac_) dllPath += ".so"; const long openmode=RTLD_LAZY # ifdef OSMac_ | RTLD_LOCAL # endif // OSMac_ ; void *hDll=dlopen(dllPath.asChar(), openmode); if (!hDll) { const int errBufLen=512; char *errBuf=(char*)alloca(errBufLen); errBuf[errBufLen]='\0'; snprintf(errBuf, errBufLen, "dlopen(%s) failed: %s", dllPath.asChar(), dlerror()); MGlobal::displayError(errBuf); loadShaveVRayExportImplFailed=true; return false; } newShaveVrayExporter=(TFnNewShaveVrayExporter)dlsym(hDll, "newShaveVrayExporter"); deleteShaveVrayExporter=(TFnDeleteShaveVrayExporter)dlsym(hDll, "deleteShaveVrayExporter"); #endif if (!newShaveVrayExporter || !deleteShaveVrayExporter) { newShaveVrayExporter=0; deleteShaveVrayExporter=0; MGlobal::displayError("Failed to find shaveCreateVRayPlugin function"); loadShaveVRayExportImplFailed=true; #if defined(_WIN32) FreeLibrary(hDll); #elif defined(__linux__) || defined(OSMac_) dlclose(hDll); #endif return false; } return true; } /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ | API type and name | /~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ MTypeId shaveVrayNode::typeId(0x001029B9); MString shaveVrayNode::typeName("shaveVrayShader"); MString shaveVrayNode::apiType("VRayGeometry"); //Vray related MString shaveVrayNode::classification("geometry"); //Vray related /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ | Attributes | /~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ MObject shaveVrayNode::m_vrayGeomInfo; MObject shaveVrayNode::m_vrayGeomResult; MObject shaveVrayNode::m_outApiType; MObject shaveVrayNode::m_outApiClassification; MObject shaveVrayNode::m_iconSize; MObject shaveVrayNode::m_outMesh; MObject shaveVrayNode::m_stackIndex; MObject shaveVrayNode::m_isInstanced; MObject shaveVrayNode::m_instanceMesh; MObject shaveVrayNode::m_tipfade; MObject shaveVrayNode::m_spectint; MObject shaveVrayNode::m_spectint2; MObject shaveVrayNode::m_squirrel; MObject shaveVrayNode::m_ownshader; MObject shaveVrayNode::m_selfshadow; MObject shaveVrayNode::m_castshadow; MObject shaveVrayNode::m_recvshadow; MObject shaveVrayNode::m_primaryvis; MObject shaveVrayNode::m_reflvis; MObject shaveVrayNode::m_refrvis; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ | Attribute Names | /~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ MString shaveVrayNode::attr_vrayGeomInfo = "vrayGeomInfo"; MString shaveVrayNode::attr_vgi = "vgi"; MString shaveVrayNode::attr_vrayGeomResult = "vrayGeomResult"; MString shaveVrayNode::attr_vgr = "vgr"; MString shaveVrayNode::attr_outApiType = "outApiType"; MString shaveVrayNode::attr_oat = "oat"; MString shaveVrayNode::attr_outApiClassification= "outApiClassification"; MString shaveVrayNode::attr_oac = "oac"; MString shaveVrayNode::attr_output = "output"; MString shaveVrayNode::attr_out = "out"; MString shaveVrayNode::attr_stackIndex = "stackIndex"; MString shaveVrayNode::attr_sti = "sti"; MString shaveVrayNode::attr_isInstanced = "isInstanced"; MString shaveVrayNode::attr_isi = "isi"; MString shaveVrayNode::attr_instanceMesh = "instanceMesh"; MString shaveVrayNode::attr_ime = "ime"; MString shaveVrayNode::attr_tipfade = "tipfade"; MString shaveVrayNode::attr_tf = "tf"; MString shaveVrayNode::attr_specTint = "specTint"; MString shaveVrayNode::attr_st = "st"; MString shaveVrayNode::attr_specTint2 = "specTint2"; MString shaveVrayNode::attr_st2 = "st2"; MString shaveVrayNode::attr_squirrel = "squirrel"; MString shaveVrayNode::attr_sq = "sq"; MString shaveVrayNode::attr_ownshader = "ownshader"; MString shaveVrayNode::attr_osh = "osh"; MString shaveVrayNode::attr_selfshadow = "selfshadow"; MString shaveVrayNode::attr_ss = "ss"; MString shaveVrayNode::attr_castshadow = "castshadow"; MString shaveVrayNode::attr_cs = "cs"; MString shaveVrayNode::attr_recvshadow = "recvshadow"; MString shaveVrayNode::attr_rs = "rs"; MString shaveVrayNode::attr_primaryvis = "primaryvis"; MString shaveVrayNode::attr_pv = "pv"; MString shaveVrayNode::attr_refrvis = "refrvis"; MString shaveVrayNode::attr_rr = "rr"; MString shaveVrayNode::attr_reflvis = "reflvis"; MString shaveVrayNode::attr_rl = "rl"; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ | Methods | /~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ shaveVrayNode::shaveVrayNode(): m_vrayExporter(NULL) { if (loadShaveVRayExportImpl()) { m_vrayExporter = newShaveVrayExporter(); } else { MGlobal::displayError("You will not be able to render with V-Ray"); } } shaveVrayNode::~shaveVrayNode() { if (m_vrayExporter) { deleteShaveVrayExporter(m_vrayExporter); m_vrayExporter = NULL; } } MStatus shaveVrayNode::initialize() { MFnNumericAttribute nAttr; MFnTypedAttribute tAttr; MFnUnitAttribute uAttr; // Create input attributes m_vrayGeomInfo=nAttr.createAddr(attr_vrayGeomInfo, attr_vgi); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setStorable(false)); CHECK_MSTATUS(nAttr.setReadable(true)); CHECK_MSTATUS(nAttr.setWritable(true)); CHECK_MSTATUS(nAttr.setHidden(true)); m_vrayGeomResult=nAttr.create(attr_vrayGeomResult, attr_vgr, MFnNumericData::kInt); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setStorable(false)); CHECK_MSTATUS(nAttr.setReadable(true)); CHECK_MSTATUS(nAttr.setWritable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); MFnStringData strData; strData.create(shaveVrayNode::apiType); m_outApiType = tAttr.create(attr_outApiType, attr_oat, MFnData::kString, strData.object()); CHECK_MSTATUS(tAttr.setStorable(true)); CHECK_MSTATUS(tAttr.setKeyable(false)); CHECK_MSTATUS(tAttr.setHidden(true)); strData.create(shaveVrayNode::classification); m_outApiClassification = tAttr.create(attr_outApiClassification, attr_oac, MFnData::kString, strData.object()); CHECK_MSTATUS(tAttr.setStorable(true)); CHECK_MSTATUS(tAttr.setKeyable(false)); CHECK_MSTATUS(tAttr.setHidden(true)); m_iconSize=nAttr.create("iconSize", "is", MFnNumericData::kFloat, 1.0); CHECK_MSTATUS(nAttr.setKeyable(true)); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setReadable(true)); CHECK_MSTATUS(nAttr.setWritable(true)); m_outMesh = tAttr.create(attr_output, attr_out, MFnMeshData::kMesh); CHECK_MSTATUS(tAttr.setKeyable(false)); //CHECK_MSTATUS(tAttr.setStorable(false)); //CHECK_MSTATUS(tAttr.setReadable(true)); //CHECK_MSTATUS(tAttr.setWritable(false)); m_stackIndex = nAttr.create(attr_stackIndex,attr_sti,MFnNumericData::kInt,0); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_isInstanced = nAttr.create(attr_isInstanced,attr_isi,MFnNumericData::kBoolean,false); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_ownshader = nAttr.create(attr_ownshader,attr_osh,MFnNumericData::kBoolean,true); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_tipfade = nAttr.create(attr_tipfade,attr_tf,MFnNumericData::kBoolean,false); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_spectint = nAttr.createColor(attr_specTint,attr_st); CHECK_MSTATUS(nAttr.setDefault(1.0f, 1.0f, 1.0f)); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_spectint2 = nAttr.createColor(attr_specTint2,attr_st2); CHECK_MSTATUS(nAttr.setDefault(0.0f, 0.0f, 0.0f)); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_squirrel = nAttr.create(attr_squirrel,attr_sq,MFnNumericData::kBoolean,false); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_instanceMesh = tAttr.create(attr_instanceMesh,attr_ime,MFnData::kMesh); CHECK_MSTATUS(tAttr.setStorable(true)); CHECK_MSTATUS(tAttr.setHidden(true)); m_selfshadow = nAttr.create(attr_selfshadow,attr_ss,MFnNumericData::kFloat,1.0); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_castshadow = nAttr.create(attr_castshadow,attr_cs,MFnNumericData::kBoolean,1); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_recvshadow = nAttr.create(attr_recvshadow,attr_rs,MFnNumericData::kBoolean,1); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_primaryvis = nAttr.create(attr_primaryvis,attr_pv,MFnNumericData::kBoolean,1); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_reflvis = nAttr.create(attr_reflvis,attr_rl,MFnNumericData::kBoolean,1); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); m_refrvis = nAttr.create(attr_refrvis,attr_rr,MFnNumericData::kBoolean,1); CHECK_MSTATUS(nAttr.setStorable(true)); CHECK_MSTATUS(nAttr.setKeyable(false)); CHECK_MSTATUS(nAttr.setHidden(true)); // Add attributes CHECK_MSTATUS(addAttribute(m_vrayGeomInfo)); CHECK_MSTATUS(addAttribute(m_vrayGeomResult)); CHECK_MSTATUS(addAttribute(m_outApiType)); CHECK_MSTATUS(addAttribute(m_outApiClassification)); CHECK_MSTATUS(addAttribute(m_iconSize)); CHECK_MSTATUS(addAttribute(m_outMesh)); CHECK_MSTATUS(addAttribute(m_stackIndex)); CHECK_MSTATUS(addAttribute(m_isInstanced)); CHECK_MSTATUS(addAttribute(m_ownshader)); CHECK_MSTATUS(addAttribute(m_tipfade)); CHECK_MSTATUS(addAttribute(m_spectint)); CHECK_MSTATUS(addAttribute(m_spectint2)); CHECK_MSTATUS(addAttribute(m_squirrel)); CHECK_MSTATUS(addAttribute(m_instanceMesh)); CHECK_MSTATUS(addAttribute(m_selfshadow)); CHECK_MSTATUS(addAttribute(m_recvshadow)); CHECK_MSTATUS(addAttribute(m_castshadow)); CHECK_MSTATUS(addAttribute(m_primaryvis)); CHECK_MSTATUS(addAttribute(m_refrvis)); CHECK_MSTATUS(addAttribute(m_reflvis)); // Attribute affects CHECK_MSTATUS(attributeAffects(m_vrayGeomInfo, m_vrayGeomResult)); CHECK_MSTATUS(attributeAffects(m_iconSize, m_outMesh)); return MS::kSuccess; } // V-Ray will attempt to compute the "vrayGeomResult" output of the plugin; // at that point the plugin must add itself to the V-Ray scene description. MStatus shaveVrayNode::compute(const MPlug &plug, MDataBlock &block) { //printf("shaveVrayNode::compute(...) plug %s\n",plug.name().asChar());fflush(stdout); if (plug==m_vrayGeomResult) { if (!m_vrayExporter) { MGlobal::displayError("Couldn't load Shave V-Ray Exporter!"); return MStatus::kFailure; } //printf("m_vrayGeomResult\n");fflush(stdout); #ifdef _DEBUG MGlobal::displayInfo("shaveVrayNode::compute( m_vrayGeomResult ...)"); #endif MDataHandle geomInfoHandle=block.inputValue(m_vrayGeomInfo); void *geomInfo=geomInfoHandle.asAddr(); ///////// debug info ///////// //printf("VR::VRayGeomInfo %s\n", geomInfo != NULL ? "not NULL" : "NULL");fflush(stdout); //printf("vrayGeomInfo %s\n", gi.isConnected() ? "not connected" : "connected");fflush(stdout); ///////////////////////////// if (geomInfo) { MDataHandle idxHandle=block.inputValue(m_stackIndex); int stackIdx = idxHandle.asInt(); MDataHandle isiHandle = block.inputValue(m_isInstanced); bool isInstanced = isiHandle.asBool(); MDataHandle oshHandle = block.inputValue(m_ownshader); bool ownshader = oshHandle.asBool(); MDataHandle tfHandle = block.inputValue(m_tipfade); bool tipfade = tfHandle.asBool(); MDataHandle spHandle = block.inputValue(m_spectint); MColor spectint = MColor(spHandle.asFloat3()); MDataHandle sp2Handle = block.inputValue(m_spectint2); MColor spectint2 = MColor(sp2Handle.asFloat3()); MDataHandle sqHandle = block.inputValue(m_squirrel); bool squirrel = sqHandle.asBool(); MDataHandle imeHandle = block.inputValue(m_instanceMesh); MObject instance = imeHandle.asMesh(); MDataHandle ssHandle = block.inputValue(m_selfshadow); float selfShadow = ssHandle.asFloat(); //cast/recieve Shadows MDataHandle csHandle = block.inputValue(m_castshadow); bool castShadow = csHandle.asBool(); MDataHandle rsHandle = block.inputValue(m_recvshadow); bool recvShadow = rsHandle.asBool(); //primary visibility MDataHandle pvHandle = block.inputValue(m_primaryvis); bool primaryVis = pvHandle.asBool(); MDataHandle rlHandle = block.inputValue(m_reflvis); bool reflVis = rlHandle.asBool(); MDataHandle rrHandle = block.inputValue(m_refrvis); bool refrVis = rrHandle.asBool(); if (m_vrayVersion == "") { MGlobal::executeCommand("vray version", m_vrayVersion); } MString libPath; if(GetLibPath(m_vrayVersion, libPath)) { #if defined(OSMac_) && !defined(OSMac_MachO_) libPath = shaveMacCarbon::makeMacFilename(libPath); #endif } else { MGlobal::displayWarning("shaveVrayNode: can not retrieve V-Ray plug-ins directory from enviornment variable, default path is used."); libPath = ""; } bool camVis = true; bool lightVis = true; bool giVis = true; for (MItDependencyNodes iterNodes; !iterNodes.isDone(); iterNodes.next()) { MObject node = iterNodes.item(); MFnDependencyNode gFn(node); if (gFn.typeId() == shaveGlobals::id) { MPlug cp = gFn.findPlug("primCameraVis"); MPlug lp = gFn.findPlug("primLightVis"); MPlug gp = gFn.findPlug("primGiVis"); cp.getValue(camVis); lp.getValue(lightVis); gp.getValue(giVis); } } if (!castShadow) { lightVis = false; } if (!primaryVis) { camVis = false; } m_vrayExporter->createVRayPlugin( geomInfo, libPath, stackIdx, ownshader, isInstanced, instance, tipfade, squirrel, spectint, spectint2, camVis, lightVis, giVis, reflVis, refrVis, selfShadow, recvShadow); } MDataHandle geomResultHandle=block.outputValue(m_vrayGeomResult); geomResultHandle.asInt()=1; geomResultHandle.setClean(); return MS::kSuccess; } else if (plug == m_outMesh) { //printf("m_outMesh\n");fflush(stdout); MDataHandle sizeHandle=block.inputValue(m_iconSize); float size=sizeHandle.asFloat(); MStatus stat; MFnMeshData dataCreator; MDataHandle outputHandle=block.outputValue(m_outMesh); MObject newOutputData=dataCreator.create(); MFnMesh fnMesh; MPointArray vertices; vertices.setLength(4); vertices[0]=MPoint(-size, 0.0f, -size); vertices[1]=MPoint(-size, 0.0f, size); vertices[2]=MPoint(size, 0.0f, size); vertices[3]=MPoint(size, 0.0f, -size); fnMesh.addPolygon(vertices, true, 0.0f, newOutputData); outputHandle.set(newOutputData); outputHandle.setClean(); return MS::kSuccess; } return MS::kUnknownParameter; } bool shaveVrayNode::readDraToParam(const char *draFilename) { if (!m_vrayExporter) { return false; } return m_vrayExporter->readDraToParam(draFilename); } #endif //USE_VRAY