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

# volumeShader.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 VolumeNode : public MPxNode
    {
        public:
                         VolumeNode();
        virtual         ~VolumeNode();

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

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

        static  MTypeId id;

        private:

        static MObject aColor;
        static MObject aInputValue;
        static MObject aOutColor;
        static MObject aOutTransparency;
        static MObject aFarPointC;
        static MObject aFarPointO;
        static MObject aFarPointW;
        static MObject aPointC;
        static MObject aPointO;
        static MObject aPointW;
        static MObject aToggleCamera;
        static MObject aToggleObject;
        static MObject aToggleWorld;
        static MObject aOutAlpha;
    };

    MTypeId VolumeNode::id( 0x81012 );

    MObject VolumeNode::aColor ;
    MObject VolumeNode::aInputValue;
    MObject VolumeNode::aOutColor;
    MObject VolumeNode::aOutTransparency;
    MObject VolumeNode::aOutAlpha;
    MObject VolumeNode::aFarPointC;
    MObject VolumeNode::aFarPointO;
    MObject VolumeNode::aFarPointW;
    MObject VolumeNode::aPointC;
    MObject VolumeNode::aPointO;
    MObject VolumeNode::aPointW;
    MObject VolumeNode::aToggleCamera;
    MObject VolumeNode::aToggleObject;
    MObject VolumeNode::aToggleWorld;

    void VolumeNode::postConstructor( )
    {
        setMPSafe(true);
    }

    //
    // DESCRIPTION:
    VolumeNode::VolumeNode()
    {
    }

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

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

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

        // Inputs
        aColor = nAttr.createColor( "color", "c" );
        CHECK_MSTATUS( nAttr.setKeyable( true ) );
        CHECK_MSTATUS( nAttr.setStorable( true ) );
        CHECK_MSTATUS( nAttr.setHidden(false) );
        CHECK_MSTATUS( nAttr.setDefault(1.0f, 1.0f, 1.0f) );

        aInputValue = nAttr.create( "distance", "d", MFnNumericData::kFloat);
        CHECK_MSTATUS( nAttr.setMin(0.0f) );
        CHECK_MSTATUS(nAttr.setMax(100000.0f) );
        CHECK_MSTATUS( nAttr.setSoftMax(1000.0f) );
        CHECK_MSTATUS( nAttr.setSoftMax(1000.0f) );
        CHECK_MSTATUS( nAttr.setKeyable(true) );
        CHECK_MSTATUS(nAttr.setStorable(true)  );
        CHECK_MSTATUS( nAttr.setDefault(1.0f) );

        aToggleCamera = nAttr.create( "cameraSpace", "cs",
                                      MFnNumericData::kBoolean);

        CHECK_MSTATUS( nAttr.setKeyable(true) );
        CHECK_MSTATUS( nAttr.setStorable(true) );
        CHECK_MSTATUS( nAttr.setHidden(false) );
        CHECK_MSTATUS( nAttr.setDefault(false) );

        aToggleObject = nAttr.create( "objectSpace", "os",
                                      MFnNumericData::kBoolean);
        CHECK_MSTATUS( nAttr.setKeyable(true) );
        CHECK_MSTATUS( nAttr.setStorable(true) );
        CHECK_MSTATUS( nAttr.setHidden(false) );
        CHECK_MSTATUS( nAttr.setDefault(false) );

        aToggleWorld = nAttr.create( "worldSpace", "ws", MFnNumericData::kBoolean);
        CHECK_MSTATUS(nAttr.setKeyable(true)  );
        CHECK_MSTATUS( nAttr.setStorable(true) );
        CHECK_MSTATUS(nAttr.setHidden(false)  );
        CHECK_MSTATUS( nAttr.setDefault(true) );

        aFarPointC = nAttr.createPoint("farPointCamera", "fc" );
        CHECK_MSTATUS(nAttr.setStorable(false)  );
        CHECK_MSTATUS( nAttr.setHidden(true) );
        CHECK_MSTATUS( nAttr.setReadable(true) );
        CHECK_MSTATUS( nAttr.setWritable(true) );

        aFarPointO = nAttr.createPoint("farPointObj", "fo" );
        CHECK_MSTATUS( nAttr.setStorable(false) );
        CHECK_MSTATUS(nAttr.setHidden(true)  );
        CHECK_MSTATUS( nAttr.setReadable(true) );
        CHECK_MSTATUS( nAttr.setWritable(true) );

        aFarPointW = nAttr.createPoint("farPointWorld", "fw" );
        CHECK_MSTATUS( nAttr.setStorable(false) );
        CHECK_MSTATUS( nAttr.setHidden(true) );
        CHECK_MSTATUS(nAttr.setReadable(true)  );
        CHECK_MSTATUS( nAttr.setWritable(true) );

        aPointC = nAttr.createPoint("pointCamera", "p" );
        CHECK_MSTATUS( nAttr.setStorable(false) );
        CHECK_MSTATUS( nAttr.setHidden(true) );
        CHECK_MSTATUS( nAttr.setReadable(true) );
        CHECK_MSTATUS( nAttr.setWritable(true) );

        aPointO = nAttr.createPoint("pointObj", "po" );
        CHECK_MSTATUS( nAttr.setStorable(false)  );
        CHECK_MSTATUS( nAttr.setHidden(true) );
        CHECK_MSTATUS( nAttr.setReadable(true) );
        CHECK_MSTATUS( nAttr.setWritable(true) );

        aPointW = nAttr.createPoint("pointWorld", "pw" );
        CHECK_MSTATUS( nAttr.setStorable(false) );
        CHECK_MSTATUS( nAttr.setHidden(true) );
        CHECK_MSTATUS( nAttr.setReadable(true) );
        CHECK_MSTATUS( nAttr.setWritable(true) );

        // Outputs

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

        aOutTransparency = nAttr.createColor( "outTransparency", "ot" );
        CHECK_MSTATUS( nAttr.setStorable(false) );
        CHECK_MSTATUS( nAttr.setHidden(false) );
        CHECK_MSTATUS( nAttr.setReadable(true) );
        CHECK_MSTATUS( nAttr.setWritable(false) );

        aOutAlpha = nAttr.create( "outAlpha", "oa", MFnNumericData::kFloat);
        CHECK_MSTATUS( nAttr.setStorable(false) );
        CHECK_MSTATUS( nAttr.setHidden(false) );
        CHECK_MSTATUS( nAttr.setReadable(true) );
        CHECK_MSTATUS( nAttr.setWritable(false) );

        CHECK_MSTATUS( addAttribute(aColor) );
        CHECK_MSTATUS( addAttribute(aInputValue) );
        CHECK_MSTATUS( addAttribute(aFarPointC) );
        CHECK_MSTATUS( addAttribute(aFarPointO) );
        CHECK_MSTATUS( addAttribute(aFarPointW) );
        CHECK_MSTATUS( addAttribute(aPointC) );
        CHECK_MSTATUS( addAttribute(aPointO) );
        CHECK_MSTATUS( addAttribute(aPointW) );
        CHECK_MSTATUS( addAttribute(aToggleCamera) );
        CHECK_MSTATUS( addAttribute(aToggleObject) );
        CHECK_MSTATUS( addAttribute(aToggleWorld) );

        CHECK_MSTATUS( addAttribute(aOutColor) );
        CHECK_MSTATUS( addAttribute(aOutTransparency) );
        CHECK_MSTATUS( addAttribute(aOutAlpha) );

        CHECK_MSTATUS( attributeAffects(aColor,  aOutColor) );
        CHECK_MSTATUS( attributeAffects(aColor,  aOutTransparency) );

        CHECK_MSTATUS( attributeAffects(aFarPointC, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aFarPointO, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aFarPointW, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aPointC, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aPointO, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aPointW, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aToggleCamera, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aToggleObject, aOutColor) );
        CHECK_MSTATUS( attributeAffects(aToggleWorld, aOutColor) );

        return MS::kSuccess;
    }

    //
    // DESCRIPTION:
    MStatus VolumeNode::compute(const MPlug& plug, MDataBlock& block )
    {
        if ((plug != aOutColor) && (plug.parent() != aOutColor) &&
            (plug != aOutTransparency) && (plug.parent() != aOutTransparency))
            return MS::kUnknownParameter;

        MFloatVector&  InputColor = block.inputValue( aColor ).asFloatVector();
        float Distance = block.inputValue( aInputValue ).asFloat();

        MFloatVector&  FarCamera = block.inputValue( aFarPointC ).asFloatVector();
        MFloatVector&  FarObject = block.inputValue( aFarPointO ).asFloatVector();
        MFloatVector&  FarWorld = block.inputValue( aFarPointW ).asFloatVector();
        MFloatVector&  PointCam = block.inputValue( aPointC ).asFloatVector();
        MFloatVector&  PointObj = block.inputValue( aPointO ).asFloatVector();
        MFloatVector&  PointWor = block.inputValue( aPointW ).asFloatVector();

        bool  Camera  = block.inputValue( aToggleCamera ).asBool();
        bool  Object  = block.inputValue( aToggleObject ).asBool();
        bool  World   = block.inputValue( aToggleWorld ).asBool();

        MFloatVector interval(0.0,0.0,0.0);
        if (Camera) {
            interval = FarCamera - PointCam;
        }
        if (Object) {
            interval = FarObject - PointObj;
        }
        if (World) {
            interval = FarWorld - PointWor;
        }

        double value,dist;
        if ((value = ((interval[0]*interval[0]) +
                     (interval[1]*interval[1]) +
                     (interval[2]*interval[2])) ))
        {
            dist = sqrt ( value );
        }
        else dist = 0.0;

        MFloatVector resultColor(0.0,0.0,0.0);
        if (dist <= Distance) {
            resultColor[0] = InputColor[0];
            resultColor[1] = InputColor[1];
            resultColor[2] = InputColor[2];
        }

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

        // set output transparency
        MFloatVector transparency(resultColor[2],resultColor[2],resultColor[2]);
        MDataHandle outTransHandle = block.outputValue( aOutTransparency );
        MFloatVector& outTrans = outTransHandle.asFloatVector();
        outTrans = transparency;
        outTransHandle.setClean( );

        MDataHandle outAlphaHandle = block.outputValue( aOutAlpha );
        float& outAlpha = outAlphaHandle.asFloat();
        outAlpha = resultColor[2];
        outAlphaHandle.setClean( );

        return MS::kSuccess;
    }

    //
    // DESCRIPTION:
    MStatus initializePlugin( MObject obj )
    {
        const MString UserClassify( "shader/volume" );

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

        return MS::kSuccess;
    }

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

        return MS::kSuccess;
    }