yTwistNode.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: yTwist.cpp
//
//  Description:
//      Example implementation of a deformer. This node
//      twists the deformed vertices around the y-axis.
//

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

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

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

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

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


#define McheckErr(stat,msg)     \
    if ( MS::kSuccess != stat ) {   \
        cerr << msg;                \
        return MS::kFailure;        \
    }



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

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

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

public:
    // yTwist attributes
    //
    static  MObject     angle;          // angle to twist
    
    static  MTypeId     id;

private:

};

MTypeId     yTwist::id( 0x8000e );

// yTwist attributes  //

MObject     yTwist::angle;


yTwist::yTwist() 
//
//  Description:
//      constructor
//
{ 
}

yTwist::~yTwist()
//
//  Description:
//      destructor
//
{}

void* yTwist::creator()
//
//  Description:
//      create the yTwist
//
{
    return new yTwist();
}

MStatus yTwist::initialize()
//
//  Description:
//      initialize the attributes
//
{
    // local attribute initialization
    //
    MFnNumericAttribute nAttr;
    angle=nAttr.create( "angle", "fa", MFnNumericData::kDouble );
        nAttr.setDefault(0.0);
        nAttr.setKeyable(true);
    addAttribute( angle); 

    // affects
    //
    attributeAffects( yTwist::angle, yTwist::outputGeom );

    return MS::kSuccess;
}

MStatus
yTwist::deform( MDataBlock& block,
                MItGeometry& iter,
                const MMatrix& /*m*/,
                unsigned int /*multiIndex*/)
//
// Method: deform
//
// Description:   Deform the point with a yTwist 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 status = MS::kSuccess;
    
    // determine the angle of the yTwist
    //
    MDataHandle angleData = block.inputValue(angle,&status);
    McheckErr(status, "Error getting angle data handle\n");
    double magnitude = angleData.asDouble();

    // determine the envelope (this is a global scale factor)
    //
    MDataHandle envData = block.inputValue(envelope,&status);
    McheckErr(status, "Error getting envelope data handle\n");  
    float env = envData.asFloat();  

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

        // do the twist
        //
        double ff = magnitude*pt.y*env;
        if (ff != 0.0) {
            double cct= cos(ff);
            double cst= sin(ff);
            double tt= pt.x*cct-pt.z*cst;
            pt.z= pt.x*cst + pt.z*cct;
            pt.x=tt;;
        }

        iter.setPosition(pt);
    }
    return status;
}

// standard initialization procedures
//

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

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