このセクションでは、デフォーマ ノードの一例である offsetNode プラグインについて説明します。このプラグインは、Maya API 開発キットで提供されています。
offset クラスは MPxDeformerNode から継承され、deform() などいくつかのバーチャル メソッドを定義します。
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); virtual MObject& accessoryAttribute() const; virtual MStatus accessoryNodeSetup(MDagModifier& cmd); public: static MObject offsetMatrix; // offset center and axis static MTypeId id; private: };
新しいデフォーマ ノードは、プラグインの初期化時に MFnPluguin の registerNode() メソッドで登録する必要があります。
MStatus initializePlugin( MObject obj ) { MStatus result; MFnPlugin plugin( obj, "Autodesk", "3.0", "Any"); result = plugin.registerNode( "offset", offset::id, offset::creator, offset::initialize, MPxNode::kDeformerNode ); return result; }
デフォーマ ノードを削除するには、MFnPlugin の deregisterNode() メソッドをコールして、これらのプラグインの登録を解除する必要があります。
MStatus uninitializePlugin( MObject obj) { MStatus result; MFnPlugin plugin( obj ); result = plugin.deregisterNode( offset::id ); return result; }
プロキシ ノードに対して新しいアトリビュートを追加し構成する場合、initialize() メソッドを使用します。以下の例では、offsetMatrix アトリビュートがノードに追加され、コネクト可能になっています。入力アトリビュート offsetMatrix への任意の変更は、出力アトリビュート outputGeom に作用します。
MStatus offset::initialize() { MFnMatrixAttribute mAttr; offsetMatrix=mAttr.create( "locateMatrix", "lm"); mAttr.setStorable(false); mAttr.setConnectable(true); ddAttribute( offsetMatrix); attributeAffects( offset::offsetMatrix, offset::outputGeom ); return MStatus::kSuccess; }
deform() メソッドは、変形を計算するためのアルゴリズムを実装します。
offset クラス内で、deform() メソッドはスカッシュ アルゴリズムを使用してポイントを変形します。ジオメトリのデータは MDataHandle によってデータ ブロックから抽出され、ジオメトリの各ポイントを変形します。deform() メソッドは、変形の成功を示すため MS::kSuccess を返します。これが返らない場合、変形時に無効なデータ入力やメモリ不足などの問題が発生しています。
このメソッドには、4 つの必須の引数があります。block 引数は、ジオメトリの情報の保存先となる、ノードのデータ ブロックを表します。iter 引数は、変形するジオメトリのイテレータです。m はローカル空間からワールド空間にポイントをトランスフォームするのに使用される行列です。multiIndex は、要求した出力ジオメトリのインデックスです。
MStatus offset::deform( MDataBlock& block, MItGeometry& iter, const MMatrix& /*m*/, unsigned int multiIndex) { MStatus returnStatus; MDataHandle envData = block.inputValue(envelope, &returnStatus); if (MS::kSuccess != returnStatus) return returnStatus; float env = envData.asFloat(); MDataHandle matData = block.inputValue(offsetMatrix, &returnStatus ); if (MS::kSuccess != returnStatus) return returnStatus; MMatrix omat = matData.asMatrix(); MMatrix omatinv = omat.inverse(); 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; pt *= omat; iter.setPosition(pt); } return returnStatus; }
上の weightValue() メソッドは、ジオメトリ内のウェイト値を返します。
各頂点、CV、ラティス ポイントのウェイト値は weightValue() メソッドによって取得され、同時にマルチ インデックスがメソッドに渡されます。そして、この値が offset アルゴリズムに統合され、希望の変形を実行することができます。
accessoryNodesetup() メソッドは、追加のノードを作成し、デフォーマ ノードにアタッチします。この例では、ロケータが作成され、その行列のアトリビュートがオフセット ノードの行列の入力にコネクトされます。
MStatus offset::accessoryNodeSetup(MDagModifier& cmd) { MStatus result; 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; }
accessoryAttribute() メソッドは、アクセサリ シェイプにコネクトされたアトリビュートを返します。この場合は、offset::offsetMatrix です。アクセサリ シェイプが削除されたら、デフォーマ ノードも自動的に削除されます。
MObject& offset::accessoryAttribute() const { return offset::offsetMatrix; }
このクラスには、その他次のような機能を持つメソッドがあります。