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

Autodesk® Maya® 2009 © 1997-2008 Autodesk, Inc. All rights reserved. Generated with doxygen 1.5.6