// Shave and a Haircut // (c) 2019 Epic Games // US Patent 6720962 #include "shaveGlobals.h" #include "shaveShadowNode.h" #include "shaveUtil.h" MTypeId shaveShadowNode::id(0x00106502); void shaveShadowNode::postConstructor( ) { setMPSafe(true); } const MString shaveShadowNode::nodeTypeName("shaveShadowNode"); MObject shaveShadowNode::IntensityValue; MObject shaveShadowNode::aPointWorld; MObject shaveShadowNode::aPointWorldX; MObject shaveShadowNode::aPointWorldY; MObject shaveShadowNode::aPointWorldZ; MObject shaveShadowNode::colorR; MObject shaveShadowNode::colorG; MObject shaveShadowNode::colorB; MObject shaveShadowNode::shadColorR; MObject shaveShadowNode::shadColorG; MObject shaveShadowNode::shadColorB; MObject shaveShadowNode::lightID; MObject shaveShadowNode::aOutIntensity; MObject shaveShadowNode::aOutColorR; MObject shaveShadowNode::aOutColorG; MObject shaveShadowNode::aOutColorB; MObject shaveShadowNode::aOutColor; MObject shaveShadowNode::color; MObject shaveShadowNode::shadColor; // // DESCRIPTION: /////////////////////////////////////////////////////// shaveShadowNode::shaveShadowNode() { } // // DESCRIPTION: /////////////////////////////////////////////////////// shaveShadowNode::~shaveShadowNode() { } // // DESCRIPTION: /////////////////////////////////////////////////////// void* shaveShadowNode::creator() { return new shaveShadowNode(); } MStatus shaveShadowNode::initialize() { MFnNumericAttribute nAttr; // User defined input value IntensityValue = nAttr.create( "Intensity", "int", MFnNumericData::kFloat); nAttr.setDefault(1.0f); nAttr.setMin(0.0f); nAttr.setMax(30.0f); nAttr.setKeyable(true); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); colorB = nAttr.create( "colorB", "cB", MFnNumericData::kFloat); nAttr.setDefault(1.0f); nAttr.setMin(0.0f); nAttr.setMax(1.0f); nAttr.setKeyable(true); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); colorG = nAttr.create( "colorG", "cG", MFnNumericData::kFloat); nAttr.setDefault(1.0f); nAttr.setMin(0.0f); nAttr.setMax(1.0f); nAttr.setKeyable(true); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); colorR = nAttr.create( "colorR", "cR", MFnNumericData::kFloat); nAttr.setDefault(1.0f); nAttr.setMin(0.0f); nAttr.setMax(1.0f); nAttr.setKeyable(true); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); shadColorB = nAttr.create( "shadowColorB", "scB", MFnNumericData::kFloat); nAttr.setDefault(1.0f); nAttr.setMin(0.0f); nAttr.setMax(1.0f); nAttr.setKeyable(true); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); shadColorG = nAttr.create( "shadowColorG", "scG", MFnNumericData::kFloat); nAttr.setDefault(1.0f); nAttr.setMin(0.0f); nAttr.setMax(1.0f); nAttr.setKeyable(true); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); shadColorR = nAttr.create( "shadowColorR", "scR", MFnNumericData::kFloat); nAttr.setDefault(1.0f); nAttr.setMin(0.0f); nAttr.setMax(1.0f); nAttr.setKeyable(true); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); aOutColorB = nAttr.create( "outColorB", "ocB", MFnNumericData::kFloat); nAttr.setKeyable(false); nAttr.setStorable(false); nAttr.setReadable(true); nAttr.setWritable(false); aOutColorG = nAttr.create( "outColorG", "ocG", MFnNumericData::kFloat); nAttr.setKeyable(false); nAttr.setStorable(false); nAttr.setReadable(true); nAttr.setWritable(false); aOutColorR = nAttr.create( "outColorR", "ocR", MFnNumericData::kFloat); nAttr.setKeyable(false); nAttr.setStorable(false); nAttr.setReadable(true); nAttr.setWritable(false); aOutColor = nAttr.create( "outColor", "oc", aOutColorR, aOutColorG, aOutColorB); nAttr.setKeyable(false); nAttr.setStorable(false); nAttr.setReadable(true); nAttr.setWritable(false); shadColor = nAttr.create( "shadColor", "sc", shadColorR, shadColorG, shadColorB); nAttr.setStorable(true); nAttr.setUsedAsColor(true); nAttr.setKeyable(true); color = nAttr.create( "color", "col", colorR, colorG, colorB); nAttr.setStorable(true); nAttr.setUsedAsColor(true); nAttr.setKeyable(true); lightID = nAttr.create( "LightID", "lid", MFnNumericData::kShort); nAttr.setDefault((short)0); nAttr.setStorable(true); nAttr.setReadable(true); nAttr.setWritable(true); // Point on surface in camera space, will be used to compute view vector aPointWorldX = nAttr.create( "pointWorldX", "px", MFnNumericData::kFloat); nAttr.setStorable(false); nAttr.setHidden(true); aPointWorldY = nAttr.create( "pointWorldY", "py", MFnNumericData::kFloat); nAttr.setStorable(false); nAttr.setHidden(true); aPointWorldZ = nAttr.create( "pointWorldZ", "pz", MFnNumericData::kFloat); nAttr.setStorable(false); nAttr.setHidden(true); aPointWorld = nAttr.create( "pointWorld","p", aPointWorldX, aPointWorldY, aPointWorldZ); nAttr.setStorable(false); nAttr.setHidden(true); nAttr.setReadable(true); nAttr.setWritable(true); // Outputs // // Always set your output attributes to be read-only // You should also mark any internal attributes that your node // computes to be read-only also, this will prevent any connections. aOutIntensity = nAttr.create( "outIntensity", "oi", MFnNumericData::kFloat); nAttr.setStorable(false); nAttr.setHidden(false); nAttr.setReadable(true); nAttr.setWritable(false); addAttribute(aOutColor); addAttribute(shadColor); addAttribute(color); addAttribute(IntensityValue); addAttribute(aPointWorld); addAttribute(aOutIntensity); addAttribute(lightID); attributeAffects (IntensityValue, aOutColor); attributeAffects (aPointWorldX, aOutColorB); attributeAffects (aPointWorldY, aOutColorB); attributeAffects (aPointWorldZ, aOutColorB); attributeAffects (aPointWorld, aOutColorB); attributeAffects (aPointWorldX, aOutColorR); attributeAffects (aPointWorldY, aOutColorR); attributeAffects (aPointWorldZ, aOutColorR); attributeAffects (aPointWorld, aOutColorR); attributeAffects (aPointWorldX, aOutColorG); attributeAffects (aPointWorldY, aOutColorG); attributeAffects (aPointWorldZ, aOutColorG); attributeAffects (aPointWorld, aOutColorG); attributeAffects (shadColorR, aOutColor); attributeAffects (colorR, aOutColor); return MS::kSuccess; } // // DESCRIPTION: /////////////////////////////////////////////////////// MStatus shaveShadowNode::compute( const MPlug& plug, MDataBlock& block ) { bool k = false; k |= (plug == aOutColor); k |= (plug == aOutColorR); k |= (plug == aOutColorG); k |= (plug == aOutColorB); if( !k ) return MS::kUnknownParameter; short lightIndex = block.inputValue ( lightID ).asShort(); VERT wpoint; wpoint.x = block.inputValue( aPointWorldX ).asFloat(); wpoint.y = block.inputValue( aPointWorldY ).asFloat(); wpoint.z = block.inputValue( aPointWorldZ ).asFloat(); float cR = block.inputValue( colorR ).asFloat(); float cG = block.inputValue( colorG ).asFloat(); float cB = block.inputValue( colorB ).asFloat(); float sCR = block.inputValue( shadColorR ).asFloat(); float sCG = block.inputValue( shadColorG ).asFloat(); float sCB = block.inputValue( shadColorB ).asFloat(); float shadow; // // We need to get the shadow density from the shaveGlobals node. // However, it would be too expensive to call // shaveGlobals::getGlobals() on every iteration of compute, so // shaveRender::frameStart() does it for us, so we can just use the // result global vars. // if (shaveShadowDensityGlob > 0.0) { float illum = 1255.0f; int id; int minId = shaveUtil::globalLightList[lightIndex].minId; int maxId = shaveUtil::globalLightList[lightIndex].maxId; float temp=10000.0; for (id = minId; id <= maxId; id++) { temp = SHAVEilluminate_point(wpoint, id); if (temp < illum) illum = temp; // changed max to min } shadow = (1.0f - illum) * shaveShadowDensityGlob; } else shadow = shaveShadowDensityGlob; MDataHandle outColorRHandle = block.outputValue( aOutColorR ); float& oCR = outColorRHandle.asFloat(); MDataHandle outColorGHandle = block.outputValue( aOutColorG ); float& oCG = outColorGHandle.asFloat(); MDataHandle outColorBHandle = block.outputValue( aOutColorB ); float& oCB = outColorBHandle.asFloat(); oCR = cR + (sCR - cR) * shadow; oCG = cG + (sCG - cG) * shadow; oCB = cB + (sCB - cB) * shadow; outColorRHandle.setClean(); outColorGHandle.setClean(); outColorBHandle.setClean(); return MS::kSuccess; }