solidCheckerShader.cpp
#include <math.h>
#include <maya/MGlobal.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/MFnMatrixAttribute.h>
#include <maya/MFloatVector.h>
#include <maya/MFloatPoint.h>
#include <maya/MFloatMatrix.h>
#include <maya/MFnPlugin.h>
class mySChecker : public MPxNode
{
        public:
        mySChecker();
        virtual ~mySChecker();
        virtual MStatus compute( const MPlug&, MDataBlock& );
        virtual void    postConstructor();
        static  void *  creator();
        static  MStatus initialize();
        
        static const MTypeId id;
        private:
        
        static MObject aColor1;
        static MObject aColor2;
        static MObject aPlaceMat;
        static MObject aPointWorld;
    static MObject aBias;
        
        static MObject aOutColor;
        static MObject aOutAlpha;
};
const MTypeId mySChecker::id( 0x8100b );
MObject        mySChecker::aColor1;
MObject        mySChecker::aColor2;
MObject        mySChecker::aPlaceMat;
MObject        mySChecker::aPointWorld;
MObject        mySChecker::aBias;
 
MObject        mySChecker::aOutColor;
MObject        mySChecker::aOutAlpha;
#define MAKE_INPUT(attr)                                                                \
    attr.setKeyable(true);  attr.setStorable(true);             \
    attr.setReadable(true); attr.setWritable(true);
#define MAKE_OUTPUT(attr)                                                               \
    attr.setKeyable(false); attr.setStorable(false);    \
    attr.setReadable(true); attr.setWritable(false);
void mySChecker::postConstructor( )
{
        setMPSafe(true);
}
mySChecker::mySChecker()
{
}
mySChecker::~mySChecker()
{
}
void * mySChecker::creator()
{
    return new mySChecker();
}
MStatus mySChecker::initialize()
{
    MFnMatrixAttribute mAttr; 
    MFnNumericAttribute nAttr; 
        MObject x, y, z;
        aColor1 = nAttr.createColor("color1", "c1");
        MAKE_INPUT(nAttr);
        nAttr.setDefault(0., .58824, .644);             
        aColor2 = nAttr.createColor("color2", "c2");
        MAKE_INPUT(nAttr);
        nAttr.setDefault(1., 1., 1.);                   
    aBias = nAttr.create( "bias", "b", MFnNumericData::k3Float);
        MAKE_INPUT(nAttr);
    nAttr.setMin(0.0f);
    nAttr.setMax(1.0f);
    nAttr.setDefault(0.5f, 0.5f, 0.5f);
    aPlaceMat = mAttr.create("placementMatrix", "pm",
                                                         MFnMatrixAttribute::kFloat);
    MAKE_INPUT(mAttr);
        
    aPointWorld = nAttr.createPoint("pointWorld", "pw");
        MAKE_INPUT(nAttr);
    nAttr.setHidden(true);
        
    aOutColor = nAttr.createColor("outColor", "oc");
        MAKE_OUTPUT(nAttr);
    aOutAlpha = nAttr.create( "outAlpha", "oa", MFnNumericData::kFloat);
        MAKE_OUTPUT(nAttr);
    
    addAttribute(aColor1);
    addAttribute(aColor2);
    addAttribute(aPointWorld);
    addAttribute(aPlaceMat);
    addAttribute(aBias);
    addAttribute(aOutColor);
    addAttribute(aOutAlpha);
    
    attributeAffects (aColor1, aOutColor);
    attributeAffects (aColor1, aOutAlpha);
    attributeAffects (aColor2, aOutColor);
    attributeAffects (aColor2, aOutAlpha);
    attributeAffects (aPointWorld, aOutColor);
    attributeAffects (aPointWorld, aOutAlpha);
    attributeAffects (aPlaceMat, aOutColor);
    attributeAffects (aPlaceMat, aOutAlpha);
    attributeAffects (aBias, aOutColor);
    attributeAffects (aBias, aOutAlpha);
    return MS::kSuccess;
}
MStatus mySChecker::compute(const MPlug& plug, MDataBlock& block) 
{
        
    if((plug != aOutColor) && (plug.parent() != aOutColor) && 
           (plug != aOutAlpha))
                return MS::kUnknownParameter;
        MFloatVector resultColor;
        float3 & worldPos = block.inputValue(aPointWorld).asFloat3();
        MFloatMatrix& mat = block.inputValue(aPlaceMat).asFloatMatrix();
    float3 & bias = block.inputValue(aBias).asFloat3();
        MFloatPoint pos(worldPos[0], worldPos[1], worldPos[2]);
        pos *= mat;                                                             
    
    int count = 0;
        if (pos.x - floor(pos.x) < bias[0]) count++;
        if (pos.y - floor(pos.y) < bias[1]) count++;
        if (pos.z - floor(pos.z) < bias[2]) count++;
    if (count & 1)
                resultColor = block.inputValue(aColor2).asFloatVector();
        else
                resultColor = block.inputValue(aColor1).asFloatVector();
        
        MDataHandle outColorHandle = block.outputValue( aOutColor );
        MFloatVector& outColor = outColorHandle.asFloatVector();
        outColor = resultColor;
        outColorHandle.setClean();
    
        MDataHandle outAlphaHandle = block.outputValue( aOutAlpha );
        float& outAlpha = outAlphaHandle.asFloat();
        outAlpha = ( count & 1) ? 1.0f : 0.0f;
        outAlphaHandle.setClean();
    return MS::kSuccess;
}
MStatus initializePlugin( MObject obj )
{
    const MString UserClassify( "texture/3d" );
    MFnPlugin plugin( obj, PLUGIN_COMPANY, "4.5", "Any");
    plugin.registerNode("solidChecker", mySChecker::id, 
                                                &mySChecker::creator, &mySChecker::initialize,
                                                MPxNode::kDependNode, &UserClassify );
    return MS::kSuccess;
}
MStatus uninitializePlugin( MObject obj )
{
    MFnPlugin plugin( obj );
    plugin.deregisterNode( mySChecker::id );
    return MS::kSuccess;
}