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

# shiftNode.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 <maya/MFnPlugin.h>
    #include <maya/MPxNode.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>

    // Error macro: if not successful, print error message and return
    // the MStatus instance containing the error code.
    // Assumes that "stat" contains the error value
    #define PERRORfail(stat,msg) \
        if (!(stat)) { stat.perror((msg)); return (stat); }

    // Forward Declarations //

    class shiftNode;

    // Plugin Lambert Shader Class //

    class shiftNode : public MPxNode
    {
        public: // Methods
        shiftNode();
        virtual ~shiftNode();

        virtual MStatus compute( const MPlug&, MDataBlock& );

        static  void *          creator();
        static  MStatus         initialize();

        //  Id tag for use with binary file format
        static MTypeId id;

        private:

        float ox, oy, oz;
        int initID, doneID;
        static bool firstTime;

        // Input
        static MObject aShift;
        static MObject aDist;

        static MObject aColor;

        static MObject aRefPointCamera;
        static MObject aUv;

        // Output
        static MObject aOutColor;

    };

    // attribute information

    MTypeId shiftNode::id( 0x8001a );

    // input

    MObject     shiftNode::aShift;
    MObject     shiftNode::aDist;
    MObject     shiftNode::aColor;
    MObject     shiftNode::aRefPointCamera;
    MObject     shiftNode::aUv;

    // output

    MObject     shiftNode::aOutColor;

    shiftNode::shiftNode()
    {
    }

    shiftNode::~shiftNode()
    {
    }

    // creates an instance of the node
    void * shiftNode::creator()
    {
        return new shiftNode();
    }

    // initializes attribute information
    MStatus shiftNode::initialize()
    {
        MStatus stat;

        MFnNumericAttribute nAttr;

        // shift

        aShift = nAttr.create( "shift", "sh",
                              MFnNumericData::kBoolean, false );
        stat = addAttribute( aShift );
        PERRORfail( stat, "addAttribute shift" );

        // distance

        aDist = nAttr.create( "distance", "dis",
                             MFnNumericData::kFloat, 0.0 );
        stat = addAttribute( aDist );
        PERRORfail( stat, "addAttribute dist" );

        // inColor

        aColor = nAttr.createColor( "color", "c" );
        nAttr.setStorable(false);
        stat = addAttribute( aColor );
        PERRORfail( stat, "addAttribute inColor" );

        // refPointCamera

        aRefPointCamera = nAttr.createPoint( "refPointCamera", "rpc" );
        nAttr.setStorable(false);
        nAttr.setWritable(true);
        nAttr.setRenderSource(true);
        nAttr.setHidden(true);
        stat = addAttribute( aRefPointCamera );
        PERRORfail( stat, "addAttribute refPointCamera" );

        // uv

        MObject u = nAttr.create( "uCoord", "u", MFnNumericData::kFloat, 0.0 );
        MObject v = nAttr.create( "vCoord", "v", MFnNumericData::kFloat, 0.0 );
        aUv = nAttr.create( "uvCoord", "uv", u, v );
        nAttr.setStorable(false);
        nAttr.setWritable(true);
        nAttr.setRenderSource(true);
        nAttr.setHidden(true);
        stat = addAttribute( aUv );
        PERRORfail( stat, "addAttribute uv" );

        // create output attributes here

        aOutColor = nAttr.createColor( "outColor", "oc" );
        PERRORfail(stat, "initialize create outColor attribute");
        nAttr.setReadable( true );
        nAttr.setWritable( false );
        stat = addAttribute( aOutColor );
        PERRORfail(stat, "addAttribute(outColor)");

        // attribute affects

        attributeAffects ( aShift, aOutColor );
        attributeAffects ( aDist, aOutColor );
        attributeAffects ( aColor, aOutColor );
        attributeAffects ( aRefPointCamera, aOutColor );
        attributeAffects ( aUv, aOutColor );

        // we need to do the followings to cause other input attributes
        // to evaluate with the new values we set

        attributeAffects ( aUv, aUv );
        attributeAffects ( aRefPointCamera, aRefPointCamera );

        return MS::kSuccess;
    }

    /*

    This function gets called by Maya to evaluate the texture.

    */
    MStatus shiftNode::compute( const MPlug& plug, MDataBlock& data )
    {
        MStatus stat;

        if ((plug != aOutColor) && (plug.parent() != aOutColor))
            return MS::kUnknownParameter;

        MDataHandle colorH;
        MFloatVector color;

        MDataHandle shiftH = data.inputValue( aShift, &stat);
        PERRORfail(stat, "compute getting shift attr");
        bool shiftIt = shiftH.asBool();

        MDataHandle distH = data.inputValue( aDist, &stat);
        PERRORfail(stat, "compute getting distance attr");
        float distance = distH.asFloat();

        MFloatVector clr;

        if ( shiftIt && distance != 0.0 )
        {
            // first evaluate color at default sample posiiton

            clr = data.inputValue( aColor ).asFloatVector();

            // uv is used by 2d textures
            // refPointCamera is used by 3d textures

            MDataHandle refPointCamH = data.inputValue( aRefPointCamera, &stat);
            PERRORfail(stat, "compute getting refPointCamera attr");
            MFloatVector refPC = refPointCamH.asFloatVector();

            // get current UV

            const float2 & oldUV = data.inputValue(aUv).asFloat2();

            // shift and set the uv/refPointCamera values so
            // we can sample around the current uv/refPointCamera

            MDataHandle outUV = data.outputValue( aUv );
            MDataHandle outPC = data.outputValue( aRefPointCamera );

            outUV.set( oldUV[0]-distance, oldUV[1] );
            outPC.set( refPC.x + distance, refPC.y + distance, refPC.z + distance);
            colorH = data.inputValue( aColor, &stat);   // evaluate at new pos
            color = colorH.asFloatVector();
            clr += color;

            outUV.set( oldUV[0]+distance, oldUV[1] );
            outPC.set( refPC.x - distance, refPC.y + distance, refPC.z + distance);
            colorH = data.inputValue( aColor, &stat);   // evaluate at new pos
            color = colorH.asFloatVector();
            clr += color;

            outUV.set( oldUV[0], oldUV[1]-distance );
            outPC.set( refPC.x + distance, refPC.y - distance, refPC.z + distance);
            colorH = data.inputValue( aColor, &stat);   // evaluate at new pos
            color = colorH.asFloatVector();
            clr += color;

            outUV.set( oldUV[0], oldUV[1]+distance );
            outPC.set( refPC.x - distance, refPC.y - distance, refPC.z + distance);
            colorH = data.inputValue( aColor, &stat);   // evaluate at new pos
            color = colorH.asFloatVector();
            clr += color;

            clr /= 5.0; // average the colors from all locations

            // set sample data back to original values

            outUV.set( oldUV[0], oldUV[1] );
            outPC.set( refPC.x, refPC.y, refPC.z );
        }
        else
        {
            colorH = data.inputValue( aColor, &stat);
            clr = colorH.asFloatVector();
        }

        MDataHandle outColorHandle = data.outputValue( aOutColor );
        MFloatVector& oclr = outColorHandle.asFloatVector();
        oclr = clr;
        outColorHandle.setClean();

        return MS::kSuccess;
    }

    //
    //
    //

    MStatus initializePlugin( MObject obj )
    {
       const MString UserClassify( "utility/general" );

        MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");
        plugin.registerNode( "shiftNode", shiftNode::id,
                             shiftNode::creator, shiftNode::initialize,
                             MPxNode::kDependNode, &UserClassify );

       return MS::kSuccess;

    }

    MStatus uninitializePlugin( MObject obj )
    {
        MFnPlugin plugin( obj );
        plugin.deregisterNode( shiftNode::id );

        return MS::kSuccess;
    }