This section describes the yTwistNode
plug-in, which is an example of a deformer node. This plug-in is available through the Maya Developer Kit.
The ytwist
class inherits from MPxGeometryFilter
and defines a single virtual method, deform()
.
class yTwist : public MPxGeometryFilter
{
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:
};
The new deformer node must be registered with the registerNode()
method of MFnPlugin
when initializing the plug-in.
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;
}
To remove the deformer node, you must deregister the plug-in with a call to the deregisterNode()
method of MFnPlugin
.
MStatus uninitializePlugin( MObject obj)
{
MStatus result;
MFnPlugin plugin( obj );
result = plugin.deregisterNode( offset::id );
return result;
}
The initialize()
method is used to add and configure new attributes to proxy nodes. In the example below, the angle
attribute is added to the node and is made connectable. Any changes to the input attribute angle
affect the output attribute outputGeom
.
MStatus yTwist::initialize()
{
// 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;
}
The deform()
method implements an algorithm to compute the deformation.
In the yTwist
class, the deform()
method deforms a point with a yTwist algorithm. The geometry data is extracted from the datablock by MDataHandle
and deforms each point of the geometry. The deform()
method returns a MS::kSuccess
to indicate a successful deformation. If not, the deformation encountered problems, such as invalid data input or insufficient memory.
There are four required arguments for this method. The block
argument refers to the node’s datablock where information on the geometry is stored. The iter
argument is the iterator for the geometry to be deformed. The m
is the matrix used to transform points from local space to world space. The multiIndex
is the index of the requested output geometry. In the yTwistNode example, only the block
and the iter
arguments are used.
MStatus
yTwist::deform( MDataBlock& block,
MItGeometry& iter,
const MMatrix& /*m*/,
unsigned int /*multiIndex*/)
{
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;
}
In this example, no per-vertex weighting is used by the deformer. For an example of per-vertex weighting, see the Developer Kit example offsetNode, which inherits from MPxDeformerNode
, and uses weightValue()
to obtain the weight value for each vertex, CV or lattice point. This example also illustrates how to implement accessory nodes.
There are several other methods in MPxGeometryFilter
that allow the plug-in to: