// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 #include #include #ifdef _WIN32 #define fileno _fileno #define fstat _fstat typedef struct _stat StatType; #else #include typedef struct stat StatType; #endif #include #include #include #include #include #include #include #include "utils.h" #include "vrayexport.h" #include "plugman.h" #include "vrayplugins.h" #include "defparams.h" #include "vraymayageom.h" #include "shaveVrayExporter.h" #ifndef VRAY_OVERRIDE #define VRAY_OVERRIDE #endif #define VR VUtils class shaveVrayExporterImpl: public shaveVrayExporter { public: shaveVrayExporterImpl(); void createVRayPlugin( void *voidGeomInfo, const MString &libPath, int stackIdx, bool ownshader, bool isInstanced, const MObject &instance, bool tipfade, bool squirrel, const MColor &spec_tint, const MColor &spec_tint2, bool camVis, bool lightVis, bool giVis, bool reflVis, bool refrVis, float selfShadow, bool recvShadow ) VRAY_OVERRIDE; bool readDraToParam(const char *draFilename) VRAY_OVERRIDE; private: // V-Ray plugin parameters VR::DefIntParam m_stackIndexParam; VR::DefIntParam m_instancedParam; VR::DefIntParam m_ownshaderParam; VR::DefStringParam m_draFileParam; VR::DefIntListParam m_dataParam; VR::DefIntParam m_dataSizeParam; VR::DefStringParam m_libPathParam; VR::DefIntParam m_squirrelParam; VR::DefIntParam m_tipfadeParam; VR::DefColorParam m_spectintParam; VR::DefColorParam m_spectint2Param; //instance uvs-related params VR::DefIntParam m_numFacesPerInstParam; VR::DefIntParam m_numUVSetsParam; VR::DefVectorListParam m_uvsParam; //ray visibility params VR::DefIntParam m_cameraVisibilityParam; VR::DefIntParam m_reflVisibilityParam; VR::DefIntParam m_refrVisibilityParam; VR::DefIntParam m_lightVisibilityParam; VR::DefIntParam m_GiVisibilityParam; VR::DefFloatParam m_selfShadowParam; VR::DefIntParam m_recvShadowParam; VR::DefIntParam m_useGlobalHairTreeParam; // store all voxels in a global hair tree VR::DefIntParam m_dynamicHairTesselation; // compute sub-segments based on distance to camera VR::DefFloatParam m_hairTesselMaxEdgeLen; // max desired sub-segment length (in pixels) }; shaveVrayExporterImpl::shaveVrayExporterImpl() : m_stackIndexParam("stackId",0), m_instancedParam("instanced",0), m_ownshaderParam("ownshader",1), m_draFileParam("draFile",""), m_dataParam("draData"), m_dataSizeParam("draSize",0), m_libPathParam("libPath", ""), m_squirrelParam("squirrel",0), m_tipfadeParam("tipfade",0), m_spectintParam("spectint",VR::Color(1.0f,1.0f,1.0f)), m_spectint2Param("spectint2",VR::Color(0.0f,0.0f,0.0f)), m_numFacesPerInstParam("numFacesPerInst",0), m_numUVSetsParam("numUVSets",0), m_uvsParam("uvs"), m_cameraVisibilityParam("cameraVisibility",1), m_reflVisibilityParam("reflVisibility",1), m_refrVisibilityParam("refrVisibility",1), m_lightVisibilityParam("lightVisibility",1), m_GiVisibilityParam("GiVisibility",1), m_selfShadowParam("selfShadow",1.0f), m_recvShadowParam("recvShadow",1), m_useGlobalHairTreeParam("useGlobalHairTree",1), m_dynamicHairTesselation("dynamicHairTesselation",0), m_hairTesselMaxEdgeLen("hairTesselMaxEdgleLen",4.0f) {} void shaveVrayExporterImpl::createVRayPlugin( void *voidGeomInfo, const MString &libPath, int stackIdx, bool ownshader, bool isInstanced, const MObject &instance, bool tipfade, bool squirrel, const MColor &spec_tint, const MColor &spec_tint2, bool camVis, bool lightVis, bool giVis, bool reflVis, bool refrVis, float selfShadow, bool recvShadow) { if (!voidGeomInfo) return; MStatus stat; VR::VRayGeomInfo *geomInfo=reinterpret_cast(voidGeomInfo); // Create the VRay plugin bool existing=false; VR::VRayPluginInterface* vrplug = geomInfo->newPlugin("hairVRay30Shader", existing); if(!vrplug) { // Check for the VRay 2.4 shader. // vrplug = geomInfo->newPlugin("hairVRayShader", existing); } if(!vrplug) { MGlobal::displayError("shaveVrayExporterImpl: can not create 'hairVRayShader' or 'hairVRay30Shader' V-Ray plugin."); return; } m_stackIndexParam.setInt(stackIdx,0,0); m_ownshaderParam.setInt(ownshader ? 1 : 0,0,0); m_instancedParam.setInt(isInstanced ? 1 : 0,0,0); m_tipfadeParam.setInt(tipfade ? 1 : 0,0,0); m_squirrelParam.setInt(squirrel ? 1 : 0,0,0); m_spectintParam.setColor(VUtils::Color(spec_tint.r, spec_tint.g, spec_tint.b), 0, 0); m_spectint2Param.setColor(VUtils::Color(spec_tint2.r, spec_tint2.g, spec_tint2.b), 0, 0); m_libPathParam.setString(libPath.asChar(),0,0); /////// ray visibiltity m_cameraVisibilityParam.setInt(camVis ? 1 : 0,0,0); m_reflVisibilityParam.setInt(reflVis ? 1 : 0,0,0); m_refrVisibilityParam.setInt(refrVis ? 1 : 0,0,0); m_lightVisibilityParam.setInt(lightVis ? 1 : 0,0,0); m_GiVisibilityParam.setInt(giVis ? 1 : 0,0,0); m_selfShadowParam.setFloat(selfShadow,0,0); //printf("set selfShadow %f\n",selfShadow);fflush(stdout); m_recvShadowParam.setInt(recvShadow ? 1 : 0,0,0); if(isInstanced && !instance.isNull()) { MGlobal::displayInfo("shaveVrayExporterImpl: instance not NULL."); MFnMesh meshFn(instance); int nf = meshFn.numPolygons(); MStringArray uvSetNames; meshFn.getUVSetNames(uvSetNames); int ns = (int)uvSetNames.length(); m_numFacesPerInstParam.setInt(nf,0,0); //MGlobal::displayInfo(MString("num faces ") + nf ); m_numUVSetsParam.setInt(ns,0,0); { int count = 0; for (unsigned int i = 0; i < uvSetNames.length(); i++) { //MFloatArray u; //MFloatArray v; MIntArray numUVsPerFace; MIntArray uvIds; MString uvSet = uvSetNames[i]; stat = meshFn.getAssignedUVs(numUVsPerFace, uvIds, &uvSet); count += uvIds.length(); } m_uvsParam.setCount(count); #ifdef WIN32 MGlobal::displayInfo(MString("memory ") + (_CrtCheckMemory() ? 1 : 0)); #endif int k = 0; for (unsigned int i = 0; i < uvSetNames.length(); i++) { MFloatArray u; MFloatArray v; MIntArray numUVsPerFace; MIntArray uvIds; MString uvSet = uvSetNames[i]; stat = meshFn.getUVs(u, v, &uvSet); stat = meshFn.getAssignedUVs(numUVsPerFace, uvIds, &uvSet); for (unsigned int j = 0; j < uvIds.length(); j++) { VR::Vector V(u[uvIds[j]],v[uvIds[j]],0.0f); m_uvsParam[k] = V; k++; } } } } vrplug->setParameter(&m_stackIndexParam); vrplug->setParameter(&m_instancedParam); vrplug->setParameter(&m_ownshaderParam); vrplug->setParameter(&m_squirrelParam); vrplug->setParameter(&m_tipfadeParam); vrplug->setParameter(&m_spectintParam); vrplug->setParameter(&m_spectint2Param); vrplug->setParameter(&m_draFileParam); vrplug->setParameter(&m_dataParam); vrplug->setParameter(&m_dataSizeParam); vrplug->setParameter(&m_libPathParam); //instance uvs-related params vrplug->setParameter(&m_numFacesPerInstParam); vrplug->setParameter(&m_numUVSetsParam); vrplug->setParameter(&m_uvsParam); //ray visibility params vrplug->setParameter(&m_cameraVisibilityParam); vrplug->setParameter(&m_reflVisibilityParam); vrplug->setParameter(&m_refrVisibilityParam); vrplug->setParameter(&m_lightVisibilityParam); vrplug->setParameter(&m_GiVisibilityParam); vrplug->setParameter(&m_selfShadowParam); vrplug->setParameter(&m_recvShadowParam); vrplug->setParameter(&m_useGlobalHairTreeParam); vrplug->setParameter(&m_dynamicHairTesselation); vrplug->setParameter(&m_hairTesselMaxEdgeLen); if (!existing) { // The plugin did not exist before - we can do additional set up here, if necessary } } bool shaveVrayExporterImpl::readDraToParam(const char *draFilename) { #ifdef LINUX printf("shaveVrayExporterImpl: readDraToParam\n");fflush(stdout); #endif VR::DefIntListParam *li = &m_dataParam; VR::DefIntParam *sa = &m_dataSizeParam; if(!li) { #if 0 //we do not want to fire this warning if dummy shape is located at hidden display layer MGlobal::displayError(MString("shaveVrayExporterImpl: NULL draData parameter")); #ifdef LINUX printf("shaveVrayExporterImpl: NULL draData parameter\n");fflush(stdout); #endif #endif return false; } if(!sa) { MGlobal::displayError(MString("shaveVrayExporterImpl: NULL draDataSize parameter")); #ifdef LINUX printf("shaveVrayExporterImpl: NULL draDataSize parameter\n");fflush(stdout); #endif return false; } FILE* draFile = fopen(draFilename, "r+b"); if(!draFile) { MGlobal::displayError(MString("shaveVrayExporterImpl: can not open DRA file\n")+draFilename); #ifdef LINUX printf("shaveVrayExporterImpl: can not open DRA file %s\n",draFilename);fflush(stdout); #endif return false; } else { //Get the size of the DRA file. StatType fileInfo; fstat(fileno(draFile), &fileInfo); if(fileInfo.st_size == 0) { MGlobal::displayError("shaveVrayExporterImpl: DRA file is empty."); #ifdef LINUX printf("shaveVrayExporterImpl: DRA file is empty.");fflush(stdout); #endif return false; } else { long size = fileInfo.st_size; char* data = (char*)malloc(size); int sum = 0; int c; int p = 0; while ((c = fgetc(draFile)) != EOF) { data[p] = c; p++; sum+=c; } #ifdef LINUX printf("shaveVrayExporterImpl: checksum %i \n",sum);fflush(stdout); #endif fclose(draFile); if(p != size) { MGlobal::displayError(MString("shaveVrayExporterImpl: dra read error, bytes expected: ")+size+" bytes read: "+p); #ifdef LINUX printf("shaveVrayExporterImpl: dra read error, bytes expected %i bytes read %i \n",size,p);fflush(stdout); #endif } //pass data to vray parameter long n = size/sizeof(int); long N = n; long extra = 0; if(n*sizeof(int) < size) { N = n+1; extra = size - n*sizeof(int); } li->setCount(N); // MGlobal::displayInfo(MString("shaveVrayExporterImpl: (debug) extra bytes: ") + extra); //#ifdef LINUX // printf("shaveVrayExporterImpl: (debug) extra bytes: %i \n",extra);fflush(stdout); //#endif int* idata = (int*)data; long chpos = 0; long intsum = 0; for(long oo = 0; oo < N; oo++) { if(oo < n) { int v = idata[oo]; li->setInt(v,oo,0.0); chpos += sizeof(int); intsum += v; } else { int A = 0; char* AA = (char*)(&A); for(int j = 0; j < extra; j++) { AA[j] = data[chpos + j]; //MGlobal::displayInfo(MString("shaveVrayExporterImpl: (debug) idx: ") + (chpos + j)); //MGlobal::displayInfo(MString("shaveVrayExporterImpl: (debug) byte: ") + data[chpos + j]); } li->setInt(A,oo,0.0); chpos += extra; intsum += A; } } /////// checksum // #ifdef LINUX sum = 0; for(int oo = 0; oo < size; oo++) { sum += (unsigned char)data[oo]; } printf("shaveVrayExporterImpl: checksum %i\n",sum); fflush(stdout); printf("shaveVrayExporterImpl: intsum %i\n",intsum); fflush(stdout); ///////////// #endif free(data); sa->setInt(size,0,0); #ifdef LINUX printf("shaveVrayExporterImpl: readDraToParam - done\n");fflush(stdout); #endif return true; } } } extern "C" SHAVEVRAYEXPORTER_EXPORT shaveVrayExporter *newShaveVrayExporter() { return new shaveVrayExporterImpl(); } extern "C" SHAVEVRAYEXPORTER_EXPORT void deleteShaveVrayExporter(shaveVrayExporter *exporter) { delete exporter; }