// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 /********************************************************************** *< FILE: shaveVrayPlugin.cpp DESCRIPTION: VRay plugin CREATED BY: Vladimir Dubovoy HISTORY: created 30-03-2010 *> **********************************************************************/ #include "shaveVrayPlugin.h" #include "shaveVrayInstance.h" //regular hair #include "shaveVrayInstanceI.h" //instnanced hair #include "shaveVraySharedFunctions.h" #include #include #include extern "C" { #include "shaveSDKFUNCS2.h" } #ifdef WIN32 FILE* alog = NULL; #endif VR::CharString shaveVrayPlugin::draFile = VR::CharString(); const char* shaveVrayPlugin::version = "v1.0.18"; void shaveVrayPlugin::pause(int minSeconds, int maxSeconds) { int range = maxSeconds - minSeconds + 1; int delayInSeconds = (int)((float)rand() / (((float)RAND_MAX) + 1.0f) * (float)(range+1)) + minSeconds; #ifdef _WIN32 Sleep(delayInSeconds * 1000); #else sleep(delayInSeconds); #endif } shaveVrayPlugin::shaveVrayPlugin(VR::VRayPluginDesc *desc) : VRayStaticGeomSource(desc) { LOGMSG("SHAVE","shaveVrayPlugin ctor"); //LOGMSGS("SHAVE","version",version); fprintf(stdout,"SHAVE: Shave and A Haircut for V-Ray (%s)\n",version); fprintf(stdout,"SHAVE: Shave core (%s)\n",SHAVE2query_version()); fprintf(stdout,"SHAVE: (c) 2019 Epic Games\n"); fflush(stdout); //LOGMSG("SHAVE","SHAVE2init"); //SHAVE2init(); //crash on mac _instanced() = 0; _stackIndex()= 0; ctxs=NULL; paramList->setParamCache(VR30_CONST_STR_HACK("stackId"), &m_stackIndex); paramList->setParamCache(VR30_CONST_STR_HACK("instanced"), &m_instanced); paramList->setParamCache(VR30_CONST_STR_HACK("ownshader"), &m_ownshader); paramList->setParamCache(VR30_CONST_STR_HACK("squirrel"), &m_squirrel); paramList->setParamCache(VR30_CONST_STR_HACK("tipfade"), &m_tipfade); paramList->setParamCache(VR30_CONST_STR_HACK("spectint"), &m_spectint); paramList->setParamCache(VR30_CONST_STR_HACK("spectint2"), &m_spectint2); paramList->setParamCache(VR30_CONST_STR_HACK("draFile"), &draFile); paramList->setParamCache(VR30_CONST_STR_HACK("libPath"), &m_libPath); //instance uvs-related params paramList->setParamCache(VR30_CONST_STR_HACK("numFacesPerInst"), &m_numFacesPerInst); paramList->setParamCache(VR30_CONST_STR_HACK("numUVSets"), &m_numUVSets); //ray visibility params paramList->setParamCache(VR30_CONST_STR_HACK("cameraVisibility"), &m_cameraVisibility); paramList->setParamCache(VR30_CONST_STR_HACK("reflVisibility"), &m_reflVisibility); paramList->setParamCache(VR30_CONST_STR_HACK("refrVisibility"), &m_refrVisibility); paramList->setParamCache(VR30_CONST_STR_HACK("lightVisibility"), &m_lightVisibility); paramList->setParamCache(VR30_CONST_STR_HACK("GiVisibility"), &m_GiVisibility); paramList->setParamCache(VR30_CONST_STR_HACK("selfShadow"), &m_selfShadow); paramList->setParamCache(VR30_CONST_STR_HACK("recvShadow"), &m_recvShadow); #if defined(VRAY30) || defined(VRAY40) paramList->setParamCache(VR30_CONST_STR_HACK("useGlobalHairTree"), &useGlobalHairTree); paramList->setParamCache(VR30_CONST_STR_HACK("dynamicHairTesselation"), &dynHairTessel); paramList->setParamCache(VR30_CONST_STR_HACK("hairTesselMaxEdgleLen"), &edgeLen); #endif LOGMSG("SHAVE","shaveVrayPlugin ctor - OK"); } shaveVrayPlugin::~shaveVrayPlugin() { LOGMSG("SHAVE","shaveVrayPlugin dtor"); freeMem(); #ifdef WIN32 assert(_CrtCheckMemory()); #endif LOGMSG("SHAVE","shaveVrayPlugin dtor - OK"); } void shaveVrayPlugin::freeMem() { if (ctxs) { for (int threadIdx=0; threadIdx < numThreads; threadIdx++) if (ctxs[threadIdx]) ctxs[threadIdx]->releaseContext(); delete[] ctxs; ctxs=NULL; } } void shaveVrayPlugin::createRayContextes(VR::VRayRenderer *vray) { numThreads = vray->getSequenceData().maxRenderThreads; ctxs = new VR::VRayContext*[numThreads]; for (int threadIdx=0; threadIdxgetThreadData(threadIdx))->newVRayContext()); VR::VRayContext &rc = *(ctxs[threadIdx]); rc.clear(); VR::TraceRay tray; #if defined(VRAY30) tray.p=VR::TracePoint(0.0f, 0.0f, 0.0f); tray.dir=VR::Vector(0.0f, 0.0f, 1.0f); rc.setRay(0.0f, 0.0f, tray, VR::RT_CAMERA , 0.0f, 0.0f, LARGE_FLOAT); #elif defined(VRAY40) tray.p=VR::simd::Vector3f(0.0f, 0.0f, 0.0f); tray.dir=VR::simd::Vector3f(0.0f, 0.0f, 1.0f); VR::ShadeCol multResult; multResult.makeWhite(); rc.setRay(0.0f, 0.0f, tray, VR::RayFlags(VR::RT_CAMERA), 0.0f, 0.0f, LARGE_FLOAT); #endif // rc.rayparams.computeGBuffer=false; VR::IntersectionData isData; isData.primitive=NULL; isData.skipTag=NULL; isData.faceIndex=0; isData.sb=NULL; isData.si=NULL; isData.sd=NULL; isData.surfaceProps=NULL; isData.volume=NULL; isData.wpointCoeff=1.0f; #if defined(VRAY30) || defined(VRAY40) isData.bary=VR::ShadeVec(0.0f, 0.0f, 0.0f); isData.wpoint=VR::ShadeVec(0.0f, 0.0f, 0.0f); isData.faceBase=isData.faceEdge0=isData.faceEdge1=VR::ShadeVec(0.0f, 0.0f, 0.0f); isData.gnormal=isData.normal=VR::ShadeVec(0.0f, 0.0f, 1.0f); #endif rc.setRayResult(true, &isData, 0); #if defined(VRAY30) || defined(VRAY40) rc.rayresult.dPdx=VR::ShadeVec(0.0f, 0.0f, 0.0f); rc.rayresult.dPdy=VR::ShadeVec(0.0f, 0.0f, 0.0f); #endif } } // true if SHAVE2init() has been called so that we know to call SHAVE2cleanup() when the plugin is unloaded. int shaveInitCalled=false; // Critical section for accessing shaveInitCalled in case we have multiple renders going on at the same time VUtils::CriticalSection shaveInit_csect; static bool isRenderStarted = false; void shaveVrayPlugin::renderBegin(VR::VRayRenderer *vray) { LOGMSG("SHAVE","shaveVrayPlugin::renderBegin"); VR::ProgressCallback* progress = NULL; if (vray != NULL) { const VR::VRaySequenceData &sdata=vray->getSequenceData(); progress = sdata.progress; } // Initialize Shave (just once, the first time we render) if (!shaveInitCalled) { VUtils::CriticalSectionRAII lock(shaveInit_csect); if (!shaveInitCalled) { SHAVE2init(); shaveInitCalled=true; } } VRayStaticGeomSource::renderBegin(vray); LOGMSG("SHAVE","shaveVrayPlugin::renderBegin - OK"); } void shaveVrayPlugin::renderEnd(VR::VRayRenderer *vray) { LOGMSG("SHAVE","shaveVrayPlugin::renderEnd"); UnLoadShaveBSDFPoolLib(); VR::ProgressCallback* progress = NULL; if (vray != NULL) { const VR::VRaySequenceData &sdata=vray->getSequenceData(); progress = sdata.progress; } VRayStaticGeomSource::renderEnd(vray); LOGMSG("SHAVE","shaveVrayPlugin::renderEnd - OK"); } void shaveVrayPlugin::frameBegin(VR::VRayRenderer *vray) { LOGMSG("SHAVE","shaveVrayPlugin::frameBegin"); VRayStaticGeomSource::frameBegin(vray); //this->vray = vray; //double time=vray->getFrameData().t; //meshInfoInterface = (MeshInfoInterface*)GET_INTERFACE(meshPlugin, EXT_MESH_INFO); ////getIntListData(faceList, paramList->getParam("faceList"), time); ////getFloatListData(areaList, paramList->getParam("areaList"), time); createRayContextes(vray); ////we need to export DRA or use dra exported in shaves ::compute ? LOGMSG("SHAVE","shaveVrayPlugin::frameBegin - OK"); } void shaveVrayPlugin::frameEnd(VR::VRayRenderer *vray) { LOGMSG("SHAVE","shaveVrayPlugin::frameEnd"); freeMem(); LOGMSG("SHAVE","shaveVrayPlugin::frameEnd - OK"); } VR::VRayStaticGeometry* shaveVrayPlugin::newInstance( VR::MaterialInterface *mtl, VR::BSDFInterface *bsdf, int renderID, VR::VolumetricInterface *volume, VR::LightList *lightList, #ifdef VRAY40 const VR::Transform &baseTM, #else const VR::TraceTransform &baseTM, #endif int objectID, const tchar *userAttributes, int primaryVisibility) { LOGMSG("SHAVE","shaveVrayPlugin::newInstance"); LoadShaveBSDFPoolLib(m_libPath.ptr()); if(instanced() == 1) { return new shaveVrayInstanceI(this, mtl, bsdf, renderID, volume, lightList, baseTM, objectID, userAttributes, m_cameraVisibility); } else { //we gonna use own bsdf return new shaveVrayInstance(this, mtl, bsdf, renderID, volume, lightList, baseTM, objectID, userAttributes, m_cameraVisibility); } } void shaveVrayPlugin::deleteInstance(VR::VRayStaticGeometry *instance) { LOGMSG("SHAVE","shaveVrayPlugin::deleteInstance"); delete (shaveVrayInstance*)instance; } VR::VRayContext* shaveVrayPlugin::getVRayContext() { VR::ThreadManager *threadMan = (const_cast(vray->getSequenceData())).threadManager; if (threadMan) { int tIdx = threadMan->getThreadIndex(); // This didn't seem to work in my tests, returned -1 if (tIdx==-1) return ctxs[0]; else return ctxs[tIdx]; } return ctxs[0]; }