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

# offsetNode.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.
    // ==========================================================================
    //+

    //
    //  File: offset.cc
    //
    //  Description:
    //      Example implementation of a deformer. This node
    //      offsets vertices according to the CV's weights.
    //      The weights are set using the set editor or the
    //      percent command.
    //

    #include <string.h>
    #include <maya/MIOStream.h>
    #include <math.h>

    #include <maya/MPxDeformerNode.h>
    #include <maya/MItGeometry.h>
    #include <maya/MPxLocatorNode.h>

    #include <maya/MFnNumericAttribute.h>
    #include <maya/MFnMatrixAttribute.h>
    #include <maya/MFnMatrixData.h>

    #include <maya/MFnPlugin.h>
    #include <maya/MFnDependencyNode.h>

    #include <maya/MTypeId.h>
    #include <maya/MPlug.h>

    #include <maya/MDataBlock.h>
    #include <maya/MDataHandle.h>
    #include <maya/MArrayDataHandle.h>

    #include <maya/MPoint.h>
    #include <maya/MVector.h>
    #include <maya/MMatrix.h>

    #include <maya/MDagModifier.h>

    class offset : public MPxDeformerNode
    {
    public:
                            offset();
        virtual             ~offset();

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

        // deformation function
        //
        virtual MStatus             deform(MDataBlock&      block,
                                           MItGeometry&     iter,
                                           const MMatrix&   mat,
                                           unsigned int     multiIndex);

        // when the accessory is deleted, this node will clean itself up
        //
        virtual MObject&            accessoryAttribute() const;

        // create accessory nodes when the node is created
        //
        virtual MStatus             accessoryNodeSetup(MDagModifier& cmd);

    public:
        // local node attributes

        static  MObject     offsetMatrix;   // offset center and axis

        static  MTypeId     id;

    private:
    };

    MTypeId     offset::id( 0x8000c );

    // local attributes
    //
    MObject     offset::offsetMatrix;

    offset::offset() {}
    offset::~offset() {}

    void* offset::creator()
    {
        return new offset();
    }

    MStatus offset::initialize()
    {
        // local attribute initialization

        MFnMatrixAttribute  mAttr;
        offsetMatrix=mAttr.create( "locateMatrix", "lm");
            mAttr.setStorable(false);
            mAttr.setConnectable(true);

        //  deformation attributes
        addAttribute( offsetMatrix);

        attributeAffects( offset::offsetMatrix, offset::outputGeom );

        return MStatus::kSuccess;
    }

    MStatus
    offset::deform( MDataBlock& block,
                    MItGeometry& iter,
                    const MMatrix& /*m*/,
                    unsigned int multiIndex)
    //
    // Method: deform
    //
    // Description:   Deform the point with a squash algorithm
    //
    // Arguments:
    //   block      : the datablock of the node
    //   iter       : an iterator for the geometry to be deformed
    //   m          : matrix to transform the point into world space
    //   multiIndex : the index of the geometry that we are deforming
    //
    //
    {
        MStatus returnStatus;

        // Envelope data from the base class.
        // The envelope is simply a scale factor.
        //
        MDataHandle envData = block.inputValue(envelope, &returnStatus);
        if (MS::kSuccess != returnStatus) return returnStatus;
        float env = envData.asFloat();

        // Get the matrix which is used to define the direction and scale
        // of the offset.
        //
        MDataHandle matData = block.inputValue(offsetMatrix, &returnStatus );
        if (MS::kSuccess != returnStatus) return returnStatus;
        MMatrix omat = matData.asMatrix();
        MMatrix omatinv = omat.inverse();

        // iterate through each point in the geometry
        //
        for ( ; !iter.isDone(); iter.next()) {
            MPoint pt = iter.position();
            pt *= omatinv;

            float weight = weightValue(block,multiIndex,iter.index());

            // offset algorithm
            //
            pt.y = pt.y + env*weight;
            //
            // end of offset algorithm

            pt *= omat;
            iter.setPosition(pt);
        }
        return returnStatus;
    }

    /* override */
    MObject&
    offset::accessoryAttribute() const
    //
    //  Description:
    //    This method returns a the attribute to which an accessory
    //    shape is connected. If the accessory shape is deleted, the deformer
    //    node will automatically be deleted.
    //
    //    This method is optional.
    //
    {
        return offset::offsetMatrix;
    }

    /* override */
    MStatus
    offset::accessoryNodeSetup(MDagModifier& cmd)
    //
    //  Description:
    //      This method is called when the deformer is created by the
    //      "deformer" command. You can add to the cmds in the MDagModifier
    //      cmd in order to hook up any additional nodes that your node needs
    //      to operate.
    //
    //      In this example, we create a locator and attach its matrix attribute
    //      to the matrix input on the offset node. The locator is used to
    //      set the direction and scale of the random field.
    //
    //  Description:
    //      This method is optional.
    //
    {
        MStatus result;

        // hook up the accessory node
        //
        MObject objLoc = cmd.createNode(MString("locator"),
                                        MObject::kNullObj,
                                        &result);

        if (MS::kSuccess == result) {
            MFnDependencyNode fnLoc(objLoc);
            MString attrName;
            attrName.set("matrix");
            MObject attrMat = fnLoc.attribute(attrName);

            result = cmd.connect(objLoc,attrMat,this->thisMObject(),offset::offsetMatrix);
        }
        return result;
    }

    // standard initialization procedures
    //

    MStatus initializePlugin( MObject obj )
    {
        MStatus result;
        MFnPlugin plugin( obj, PLUGIN_COMPANY, "3.0", "Any");
        result = plugin.registerNode( "offset", offset::id, offset::creator,
                                      offset::initialize, MPxNode::kDeformerNode );

        return result;
    }

    MStatus uninitializePlugin( MObject obj)
    {
        MStatus result;
        MFnPlugin plugin( obj );
        result = plugin.deregisterNode( offset::id );
        return result;
    }