- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Examples

# interpShader.cpp

    //-
    // ==========================================================================
    // Copyright 1995,2006,2008 Autodesk, Inc. All rights reserved.
    //
    // Use of this software is subject to the terms of the Autodesk
    // license agreement provided at the time of installation or download,
    // or which otherwise accompanies this software in either electronic
    // or hard copy form.
    // ==========================================================================
    //+

    #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>

    //
    // DESCRIPTION:

    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);
    }

    //
    // DESCRIPTION:
    InterpNode::InterpNode()
    {
    }

    //
    // DESCRIPTION:
    InterpNode::~InterpNode()
    {
    }

    //
    // DESCRIPTION:
    void* InterpNode::creator()
    {
        return new InterpNode();
    }

    //
    // DESCRIPTION:
    MStatus InterpNode::initialize()
    {
         MFnNumericAttribute nAttr;

    // Inputs and Attributes
    //
    // User defined attributes require a long-name and short-name that
    // are required to be unique within the node.
    // (See the compound attribute color1 named "Sides".)
    //
    // Rendering attributes that your node wants to get from the sampler
    // require them to be defined given the pre-defined unique long-name.
    // (See the compound attribute aNormalCamera named "normalCamera".)
    //
    // User defined Attributes are generally something that you want
    // to store in the Maya file. The setStorable(true) method enables
    // an attribute to be stored into the Maya scene file.
    //
    // Rendering attributes are primarily data that is generated per sample and
    // not something that you want to store in a file. To disable an
    // attribute from being recorded to the Maya scene file use
    // the setStorable(false) method.
    //
    // Simple attributes that represent a range of values can enable a
    // slider on the Attribute Editor by using the methods setMin() and
    // setMax().
    // (See the simple attribute InputValue named "Power".)
    //
    // Compound attributes that represent a vector of 3 floats can enable
    // a color swatch on the Attribute Editor that will launch a color picker
    // tool by using the method setUsedAsColor(true).
    // (See the compound attribute color1 name "Sides".)
    //
    // Both Simple and Compound attributes can be initialized with a
    // default value using the method setDefault().
    //
    // Attributes by default show up in the Attribute Editor and
    // in the Connection Editor unless they are specified as being hidden
    // by using the method setHidden(true).
    //
    // Attributes by default have both read/write access in the dependency graph.
    // To change an attributes behaviour you can use the methods
    // setReadable() and setWritable(). The method setReadable(true)
    // indicates that the attribute can be used as the source in
    // a dependency graph connection. The method setWritable(true)
    // indicates that the attribute can be used as the destination
    // in a dependency graph connection.
    // (See the compound attribute aOutColor named "outColor" below.
    //  It has been marked as a read-only attribute since it is
    //  the computed result of the node, it is not stored in the Maya file since
    //  it is always computed, and it is marked as hidden to prevent it
    //  from being displayed in the user interface.)
    //
    //

    // User defined input value

        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) );

    // User defined color attribute
        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) );

        // Surface Normal supplied by the render sampler

        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) );

        // Point on surface in camera space, will be used to compute view vector

        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) );

    // 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.
        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;
    }

    //
    // DESCRIPTION:
    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();

        // Normalize the view vector
        CHECK_MSTATUS ( viewVector.normalize() );

        // find dot product
        float scalarNormal = (viewVector.x * surfNorm.x) +
            (viewVector.y * surfNorm.y) +
            (viewVector.z * surfNorm.z);

        // take the absolute value
        if (scalarNormal < 0.0) scalarNormal = -scalarNormal;

        // Use InputValue to change interpolation
        //     power == 1.0 linear
        //     power >= 0.0 use gamma function
        //
        float scalar;
        if (power > 0.0) {
            scalar = powf(scalarNormal, 1.0f / power);
        }
        else { scalar = 0.0; }

        // Interpolate the colors
        resultColor = Side + ((Face - Side) * scalar);

        // set ouput color attribute
        MDataHandle outColorHandle = block.outputValue( aOutColor );
        MFloatVector& outColor = outColorHandle.asFloatVector();
        outColor = resultColor;
        outColorHandle.setClean();

        return MS::kSuccess;
    }

    //
    // DESCRIPTION:
    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;
    }

    //
    // DESCRIPTION:
    MStatus uninitializePlugin( MObject obj )
    {
       MFnPlugin plugin( obj );
       CHECK_MSTATUS ( plugin.deregisterNode( InterpNode::id ) );

       return MS::kSuccess;
    }