このセクションでは、デフォーマ ノードの一例である 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);
addAttribute( 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;
}