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