interpShader.cpp
#include <math.h>
#include <maya/MPxNode.h>
#include <maya/MIOStream.h>
#include <maya/MString.h>
#include <maya/MTypeId.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MDataHandle.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MFnPlugin.h>
class InterpNode : public MPxNode
{
        public:
                  InterpNode();
        virtual       ~InterpNode();
        virtual MStatus compute( const MPlug&, MDataBlock& );
        virtual void    postConstructor();
        static  void *  creator();
        static  MStatus initialize();
        static  MTypeId id;
        private:
        static MObject aInputValue;
        static MObject aColor1;
        static MObject aColor2;
        static MObject aNormalCamera;
        static MObject aPointCamera;
        static MObject aOutColor;
};
MTypeId InterpNode::id( 0x8100e );
MObject InterpNode::aInputValue;
MObject InterpNode::aColor1;
MObject InterpNode::aColor2;
MObject InterpNode::aNormalCamera;
MObject InterpNode::aPointCamera;
MObject InterpNode::aOutColor;
void InterpNode::postConstructor( )
{
        setMPSafe(true);
}
InterpNode::InterpNode()
{
}
InterpNode::~InterpNode()
{
}
void* InterpNode::creator()
{
    return new InterpNode();
}
MStatus InterpNode::initialize()
{
     MFnNumericAttribute nAttr; 
    aInputValue = nAttr.create( "power", "pow", MFnNumericData::kFloat);
    CHECK_MSTATUS ( nAttr.setDefault(1.0f) );
    CHECK_MSTATUS ( nAttr.setMin(0.0f) );
    CHECK_MSTATUS ( nAttr.setMax(3.0f) );
    CHECK_MSTATUS ( nAttr.setKeyable(true) );
    CHECK_MSTATUS ( nAttr.setStorable(true) );
    CHECK_MSTATUS ( nAttr.setReadable(true) );
    CHECK_MSTATUS ( nAttr.setWritable(true) );
    aColor1 = nAttr.createColor( "sideColor", "sc");
    CHECK_MSTATUS ( nAttr.setDefault(1.0f, 1.0f, 1.0f) );
    CHECK_MSTATUS ( nAttr.setKeyable(true) );
    CHECK_MSTATUS ( nAttr.setStorable(true) );
    CHECK_MSTATUS ( nAttr.setUsedAsColor(true) );
    CHECK_MSTATUS ( nAttr.setReadable(true) );
    CHECK_MSTATUS ( nAttr.setWritable(true) );
    aColor2 = nAttr.createColor( "facingColor", "fc");
    CHECK_MSTATUS ( nAttr.setDefault(0.0f, 0.0f, 0.0f) );
    CHECK_MSTATUS ( nAttr.setKeyable(true) );
    CHECK_MSTATUS ( nAttr.setStorable(true) );
    CHECK_MSTATUS ( nAttr.setUsedAsColor(true) );
    CHECK_MSTATUS ( nAttr.setReadable(true) );
    CHECK_MSTATUS ( nAttr.setWritable(true) );
        
    aNormalCamera = nAttr.createPoint( "normalCamera", "n");
    CHECK_MSTATUS ( nAttr.setStorable(false) );
    CHECK_MSTATUS ( nAttr.setHidden(true) );
    CHECK_MSTATUS ( nAttr.setReadable(true) );
    CHECK_MSTATUS ( nAttr.setWritable(true) );
        
    aPointCamera = nAttr.createPoint( "pointCamera", "p");
    CHECK_MSTATUS ( nAttr.setStorable(false) );
    CHECK_MSTATUS ( nAttr.setHidden(true) );
    CHECK_MSTATUS ( nAttr.setReadable(true) );
    CHECK_MSTATUS ( nAttr.setWritable(true) );
    aOutColor  = nAttr.createColor( "outColor", "oc" );
    CHECK_MSTATUS ( nAttr.setStorable(false) );
    CHECK_MSTATUS ( nAttr.setHidden(false) );
    CHECK_MSTATUS ( nAttr.setReadable(true) );
    CHECK_MSTATUS ( nAttr.setWritable(false) );
    CHECK_MSTATUS ( addAttribute(aInputValue) );
    CHECK_MSTATUS ( addAttribute(aColor1) );
    CHECK_MSTATUS ( addAttribute(aColor2) );
    CHECK_MSTATUS ( addAttribute(aNormalCamera) );
    CHECK_MSTATUS ( addAttribute(aPointCamera) );
    CHECK_MSTATUS ( addAttribute(aOutColor) );
    CHECK_MSTATUS ( attributeAffects (aInputValue, aOutColor) );
    CHECK_MSTATUS ( attributeAffects (aColor1,  aOutColor) );
    CHECK_MSTATUS ( attributeAffects (aColor2,  aOutColor) );
    CHECK_MSTATUS ( attributeAffects (aNormalCamera,  aOutColor) );
    CHECK_MSTATUS ( attributeAffects (aPointCamera,  aOutColor) );
    return MS::kSuccess;
}
MStatus InterpNode::compute(
const MPlug&      plug,
      MDataBlock& block ) 
{ 
    if ((plug != aOutColor) && (plug.parent() != aOutColor))
                return MS::kUnknownParameter;
    MFloatVector resultColor;
    MFloatVector& Side = block.inputValue( aColor1 ).asFloatVector();
    MFloatVector& Face = block.inputValue( aColor2 ).asFloatVector();
    MFloatVector& surfNorm = block.inputValue( aNormalCamera ).asFloatVector();
    MFloatVector& viewVector = block.inputValue(aPointCamera).asFloatVector();
    float power = block.inputValue( aInputValue ).asFloat();
    
    CHECK_MSTATUS ( viewVector.normalize() );
        
    
    float scalarNormal = (viewVector.x * surfNorm.x) + 
                (viewVector.y * surfNorm.y) +
                (viewVector.z * surfNorm.z);
    
    if (scalarNormal < 0.0) scalarNormal = -scalarNormal;
    
    
    
    
        float scalar;
    if (power > 0.0) {
        scalar = powf(scalarNormal, 1.0f / power);
    }
    else { scalar = 0.0; }
    
    resultColor = Side + ((Face - Side) * scalar);
    
    MDataHandle outColorHandle = block.outputValue( aOutColor );
    MFloatVector& outColor = outColorHandle.asFloatVector();
    outColor = resultColor;
    outColorHandle.setClean();
    return MS::kSuccess;
}
MStatus initializePlugin( MObject obj )
{
   const MString UserClassify( "utility/general" );
   MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");
   CHECK_MSTATUS ( plugin.registerNode( "interpNode", InterpNode::id, 
                                                InterpNode::creator, InterpNode::initialize,
                                                MPxNode::kDependNode, &UserClassify ) );
   return MS::kSuccess;
}
MStatus uninitializePlugin( MObject obj )
{
   MFnPlugin plugin( obj );
   CHECK_MSTATUS ( plugin.deregisterNode( InterpNode::id ) );
   return MS::kSuccess;
}