このセクションでは、デフォーマ ノードの一例である 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: };
新しいデフォーマ ノードは、プラグインの初期化時に MFnPluguin の 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()メソッドをコールして、これらのプラグインの登録を解除する必要があります。
プロキシ ノードに対して新しいアトリビュートを追加し構成する場合、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 には、プラグインで次のことを可能にするメソッドがいくつかあります。