このセクションでは、デフォーマ ノードの一例であるyTwistNode プラグインについて説明します。このプラグインは、Maya Developer Kit で提供されています。
ytwist クラスは MPxGeometryFilter を継承し、1 つの仮想メソッド 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:
};
新しいデフォーマ ノードは、プラグインの初期化時に MFnPlugin の registerNode() メソッドで登録する必要があります。
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;
}
デフォーマ ノードを削除するには、MFnPlugin の deregisterNode() メソッドを呼び出して、これらのプラグインの登録を解除する必要があります。
MStatus uninitializePlugin( MObject obj)
{
MStatus result;
MFnPlugin plugin( obj );
result = plugin.deregisterNode( offset::id );
return result;
}
プロキシ ノードに対して新しいアトリビュートを追加して構成する場合は、initialize() メソッドを使用します。以下の例では、angle アトリビュートがノードに追加され、接続可能になっています。入力アトリビュート angle へのすべての変更は、出力アトリビュート 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;
}
deform() メソッドは、デフォメーションを計算するためのアルゴリズムを実装します。
yTwist クラス内で、deform() メソッドは yTwist アルゴリズムを使用してポイントを変形します。ジオメトリのデータは MDataHandle によってデータ ブロックから抽出され、ジオメトリの各ポイントを変形します。deform() メソッドは、デフォメーションの成功を示すため MS::kSuccess を返します。これが返らない場合、デフォメーション時に無効なデータ入力やメモリ不足などの問題が発生しています。
このメソッドには、4 つの必須の引数があります。block 引数は、ジオメトリの情報の保存先となる、ノードのデータ ブロックを表します。iter 引数は、変形するジオメトリのイテレータです。m はローカル空間からワールド空間にポイントをトランスフォームするのに使用される行列です。multiIndex は、要求した出力ジオメトリのインデックスです。yTwistNode のサンプルでは、block 引数と iter 引数のみが使用されます。
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;
}
この例では、頂点単位のウェイトはデフォーマに使用されません。頂点単位のウェイトの一例として Developer Kit サンプル offsetNode を参照してください。これは、MPxDeformerNode を継承し、weightValue() を使用して各頂点、CV、ラティス ポイントのウェイト値を取得します。この例でも、アクセサリ ノードを実装する方法を示します。
その他にも、MPxGeometryFilter には、プラグインで次のことを可能にするメソッドがいくつかあります。