// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 #include "shaveVrayPlugin.h" #include "shaveVrayDesc.h" #include "shaveVraySharedFunctions.h" extern "C" { #include "shaveSDKFUNCS2.h" } using namespace VR; // defined in shaveVrayPlugin.cpp; set to true if SHAVE2init() has been called. extern int shaveInitCalled; struct shaveVrayParams: public VR::VRayParameterListDesc { public: shaveVrayParams() { // Cannot initialise here because this struct is initialised // when the plugin is loaded before the check for V-Ray's // version runs and the addParamX methods of V-Ray 3 and 4 // differ. This leads to a crash on MacOS. On other OSes the // dll simply doesn't load. } void init(); virtual ~shaveVrayParams(){} }; void shaveVrayParams::init() { addParamInt (VR30_CONST_STR_HACK("stackId"), 0, -1); addParamInt (VR30_CONST_STR_HACK("instanced"),0, -1); addParamInt (VR30_CONST_STR_HACK("ownshader"),1, -1); addParamInt (VR30_CONST_STR_HACK("squirrel"),0, -1); addParamInt (VR30_CONST_STR_HACK("tipfade"),0, -1); addParamColor (VR30_CONST_STR_HACK("spectint"), VR::Color(1.0f,1.0f,1.0f), -1); addParamColor (VR30_CONST_STR_HACK("spectint2"),VR::Color(0.0f,0.0f,0.0f), -1); addParamString(VR30_CONST_STR_HACK("draFile"), "",-1); addParamString(VR30_CONST_STR_HACK("libPath"), "",-1); //uvs relaated params //DefVectorListParam is used for uvs list addParamInt(VR30_CONST_STR_HACK("numFacesPerInst"),0,-1); addParamInt(VR30_CONST_STR_HACK("numUVSets"),0,-1); //If -1, then this is not a list parameter; //if 0 then this is a list parameter of unspecified (arbitrary) length. //If this is >0, then it is the number of required elements in the parameter. addParamVector(VR30_CONST_STR_HACK("uvs"),VR::Vector(),0); addParamInt(VR30_CONST_STR_HACK("draData"),0,0); addParamInt(VR30_CONST_STR_HACK("draSize"),0,-1); //visibility related params addParamInt(VR30_CONST_STR_HACK("cameraVisibility"),1, -1); addParamInt(VR30_CONST_STR_HACK("reflVisibility"),1, -1); addParamInt(VR30_CONST_STR_HACK("refrVisibility"),1, -1); addParamInt(VR30_CONST_STR_HACK("lightVisibility"),1, -1); addParamInt(VR30_CONST_STR_HACK("GiVisibility"),1, -1); addParamFloat(VR30_CONST_STR_HACK("selfShadow"),1.0f, -1); addParamInt(VR30_CONST_STR_HACK("recvShadow"),1, -1); #if defined(VRAY30) || defined(VRAY40) addParamInt(VR30_CONST_STR_HACK("useGlobalHairTree"),1 /*1*/, -1); addParamInt(VR30_CONST_STR_HACK("dynamicHairTesselation"),0, -1); addParamFloat(VR30_CONST_STR_HACK("hairTesselMaxEdgleLen"),4.0f, -1); #endif } #if defined(VRAY40) # define BUILT_FOR "4.0" #elif defined(VRAY30) # if VRAY_DLL_VERSION < 0x31000 # define BUILT_FOR "3.0" # elif VRAY_DLL_VERSION < 0x36000 # define BUILT_FOR "3.1" # else # define BUILT_FOR "3.6" # endif #else # define BUILT_FOR "2.0" #endif // We don't use the PLUGIN_DESC macro as we need to call the Shave cleanup function // when the plugin is unloaded. class shaveVrayPluginDesc: public VRayPluginDesc { int attachCount; VUtils::FastCriticalSection attachCsect; public: shaveVrayParams shaveVrayPlugin_params; shaveVrayPluginDesc(void):VRayPluginDesc(NULL), attachCount(0) { parameters=&shaveVrayPlugin_params; (*getNumDescs())++; DescList *nd=new DescList; nd->desc=this; nd->next=(*getFirstDesc()); (*getFirstDesc())=nd; unsigned int vr_rev = VR::getVRayRevision(); unsigned int vr_rev_max; unsigned int vr_rev_min; #if defined(VRAY40) vr_rev_min = 0x40000; vr_rev_max = 0x50000; #elif defined(VRAY30) # if VRAY_DLL_VERSION < 0x31000 vr_rev_min = 0x30000; vr_rev_max = 0x31000; # elif VRAY_DLL_VERSION < 0x36000 vr_rev_min = 0x31000; vr_rev_max = 0x36000; # else vr_rev_min = 0x31000; vr_rev_max = 0x40000; # endif #else vr_rev_min = 0; vr_rev_max = 0x30000; #endif if (vr_rev < vr_rev_min || vr_rev >= vr_rev_max) { (*getNumDescs())=0; (*getFirstDesc())=NULL; printf("Skipping shave shaders for V-Ray " BUILT_FOR ".\n");fflush(stdout); } else { shaveVrayPlugin_params.init(); printf("Loaded shave shaders for V-Ray " BUILT_FOR ".\n");fflush(stdout); } } PluginID getPluginID(void) { return shaveVrayPluginID; } Plugin* newPlugin(PluginHost *host) { return new shaveVrayPlugin(this); } void deletePlugin(Plugin *obj) { delete (shaveVrayPlugin*) obj; } bool supportsInterface(InterfaceID id) { return (id==EXT_STATIC_GEOM_SOURCE) || (id==EXT_VRAY_PLUGIN); } #ifdef VRAY40 const tchar *getName(void) { return shaveVrayPluginName; } const tchar *getDescription() const { return "Shave and a Haircut support for V-Ray"; } #else tchar *getName(void) { return const_cast(shaveVrayPluginName); } #endif const tchar *getCopyright(void) { return "(c) 2019 Epic Games"; } void attachToHost(PluginHost *host) { VUtils::FastCriticalSectionRAII lock(attachCsect); attachCount++; } void detachFromHost(PluginHost *host) { VRayPluginDesc::detachFromHost(host); VUtils::FastCriticalSectionRAII lock(attachCsect); attachCount--; // Call Shave cleanup, but only if it has been initialized for some render before. if (shaveInitCalled && attachCount==0) { SHAVE2cleanup(); shaveInitCalled=false; } } }; static shaveVrayPluginDesc desc_shaveVrayPlugin; // PLUGIN_DESC(shaveVrayPluginID, EXT_STATIC_GEOM_SOURCE, shaveVrayPluginName, shaveVrayPlugin, shaveVrayParams); PLUGIN_LIBRARY(VR30_CONST_STR_HACK("shavePlugins"), VR30_CONST_STR_HACK("shaveVrayShader plug-in.")); #ifdef WIN32 #ifdef _MANAGED #pragma managed(push, off) #endif BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { hInstance = hModule; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { #if 0 // this is handled in the PluginDesc constructor now unsigned int vr_rev = VR::getVRayRevision(); //printf("vray version 0x%x \n", vr_rev);fflush(stdout); #ifdef VRAY30 if(vr_rev < 0x30000) { //its not a cracefull exit becuse fires dll loading error //need better solution. //return FALSE; //3.0 does not fire error, while 2.0 does //gr, 3.0 does as well (*getNumDescs())=0; (*getFirstDesc())=NULL; printf("Skipping shave shaders for Vray 3.0.\n");fflush(stdout); } else printf("Shave shaders for Vray 3.0 loaded.\n");fflush(stdout); #else if(vr_rev >= 0x30000) { //its not a cracefull exit becuse fires dll loading error //need better solution. //return FALSE; (*getNumDescs())=0; (*getFirstDesc())=NULL; printf("Skipping shave shaders for Vray 2.0.\n");fflush(stdout); } else printf("Shave shaders for Vray 2.0 loaded.\n");fflush(stdout); #endif #endif char* temp = getenv("TEMP"); char path[MAX_PATH]; #ifdef DO_LOGS sprintf(path,"%s/vray_Shave.log",temp); alog = fopen(path,"w"); LOGMSG("DLL", "shaveVrayShader DLL loaded.") #endif // Don't init Shave here; do that on demand in the shaveVrayPlugin::renderBegin(). // In this way Shave is not initialized at all if it is not used in the scene. // SHAVE2init(); } break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: { // Do not cleanup Shave here; do that in the hostDetach() method of the plugin // descriptor. This is because SHAVE2cleanup() cleans up some threads and it waits for them // to complete, however calls to DllMain() are serialized and SHAVE2cleanup() may // hang indefinitely as some threads attempt to call DllMain() for DLL_THREAD_DETACH. // SHAVE2cleanup(); printf("Shave shaders for Vray unloaded.\n");fflush(stdout); #ifdef DO_LOGS if(alog) { LOGMSG("DLL", "shaveVrayShader DLL unloaded.") fclose(alog); alog = NULL; } #endif } break; } return TRUE; } #ifdef _MANAGED #pragma managed(pop) #endif #endif