ノード・プラグイン

ノード・プラグインとは

コマンド・プラグインによって新しいノードを作ることができる。

ノード・プラグインの作り方

必要なノードをプラグインとして作成すれば原理的にはどんなモデリング・アニメーション・シェーディングでもできるようになる。

ノード・プラグインに必要なメソッド

nodeName()
コンストラクター。
とりあえず空でよい。
virtual ~nodeName()
デコンストラクター。
とりあえず空でよい。
virtual MStatus compute( const MPlug& plug, MDataBlock& data )
ノードが実行する計算・処理を記述する。
static void* nodeName::creator()
ノードが作成された時にノードの実体(インスタンス)を作って返す。
static MStatus nodeName::initialize()
ノードに必要なアトリビュートの設定・登録。
MStatus initializePlugin( MObject obj )
プラグインがロードされるときに実行される。
ノードの登録などを行う。
MStatus uninitializePlugin( MObject obj )
プラグインがアンロードされるときに実行される。
ノードの登録取消などを行う。

ノード・プラグインに必要な定数

MTypeId id
プラグインごとにユニークなid番号
ローカルでテストする場合などは0x00000000以上、0x0007ffff以下の番号を指定する。
プラグインを公表する場合はAlias|Wavefrontからユニークな番号を取得する。

ノード・プラグインの例1

  1. 以下のプログラムを作る。
    #include <string.h>
    #include <iostream.h>
    #include <math.h>
    
    #include <maya/MPxNode.h>    // ノードを作るために必要
    
    #include <maya/MFnNumericAttribute.h>
    #include <maya/MFnPlugin.h>
    
    #include <maya/MString.h> 
    #include <maya/MTypeId.h> 
    #include <maya/MPlug.h>
    #include <maya/MVector.h>
    #include <maya/MDataBlock.h>
    #include <maya/MDataHandle.h>
     
    class sine : public MPxNode    // MPxNodeを継承してノードを作る
    {
    public:
    		sine();
    	virtual	~sine(); 
    	virtual MStatus	compute( const MPlug& plug, MDataBlock& data );
    	static	void*	creator();
    	static	MStatus	initialize();
    public:
    	static	MObject	input;     // 入力用アトリビュート
    	static	MObject	output;    // 出力用アトリビュート
    	static	MTypeId	id;        // プラグインのId
    };
    
    MTypeId	sine::id( 0x70000 );    // 適当なid番号(0x00000000以上、0x0007ffff以下)を決める
    MObject	sine::input;
    MObject	sine::output;
    
    sine::sine(){}     // 空で良い
    sine::~sine(){}    // 空で良い
    
    MStatus sine::compute( const MPlug& plug, MDataBlock& data )
    {
    	
    	MStatus returnStatus;
     
    	if( plug == output )    // プラグがoutputアトリビュートなら以下を実行
    	{
    		// inputアトリビュートからMDataHandleを作る
    		MDataHandle inputData = data.inputValue( input, &returnStatus );
    
    		if( returnStatus != MS::kSuccess )
    			cerr << "ERROR getting data" << endl;
    		else
    		{
    			// inputアトリビュートのMDataHandleからデータをfloatとして取り出して計算
    			float result = sinf( inputData.asFloat() ) * 10.0f;
    			// outputアトリビュートからMDataHandleを作る
    			MDataHandle outputHandle = data.outputValue( sine::output );
    			// outputアトリビュートのMDataHandleに計算結果を入れる
    			outputHandle.set( result );
    			// 計算が終ったらsetCleanを必ず呼ぶ
    			data.setClean(plug);
    		}
    	}
    	else
    	{
    		// output以外のアトリビュートにはエラー(MS::kUnknownParameter)を返す
    		return MS::kUnknownParameter;
    	}
    	// 計算が成功したら(MS::kSuccess)を返す
    	return MS::kSuccess;
    }
    
    void* sine::creator()
    {
    	return new sine();
    }
    
    MStatus sine::initialize()
    {
    	MFnNumericAttribute nAttr;
    	MStatus	stat;
    
    	// inputアトリビュートの設定
    	input = nAttr.create( "input", "in", MFnNumericData::kFloat, 0.0 );
    	// inputアトリビュートをシーンファイル保存時に書き込むように設定
     	nAttr.setStorable(true);
    
    	// outputアトリビュートの設定
    	output = nAttr.create( "output", "out", MFnNumericData::kFloat, 0.0 );
    	// outputアトリビュートを出力用に設定
    	nAttr.setWritable(false);
    	// outputアトリビュートをシーンファイル保存時に書き込まないように設定
    	nAttr.setStorable(false);
    
    	// inputアトリビュートの登録
    	stat = addAttribute( input );
    	if(!stat)
    	{
    		stat.perror("addAttribute");
    		return stat;
    	}
    	// outputアトリビュートの登録
    	stat = addAttribute( output );
    	if(!stat)
    	{
    		stat.perror("addAttribute");
    		return stat;
    	}
    	// inputアトリビュートに新しい値が入って来たら
    	// outputアトリビュートを計算(compute())するように設定
    	stat = attributeAffects( input, output );
    	if(!stat)
    	{
    		stat.perror("attributeAffects");
    		return stat;
    	}
    	return MS::kSuccess;
    }
    
    MStatus initializePlugin( MObject obj )
    { 
    	MStatus	status;
    	MFnPlugin plugin( obj, "Alias|Wavefront - Example", "2.0", "Any");
    
    	status = plugin.registerNode( "sine", sine::id, sine::creator,
    								  sine::initialize );
    	if(!status)
    	{
    		status.perror("registerNode");
    		return status;
    	}
    	return status;
    }
    
    MStatus uninitializePlugin( MObject obj)
    {
    	MStatus	status;
    	MFnPlugin plugin( obj );
    
    	status = plugin.deregisterNode( sine::id );
    	if(!status)
    	{
    		status.perror("deregisterNode");
    		return status;
    	}
    	return status;
    }
    
  2. プログラムをコンパイルしMAYAにプラグインとしてロードする。
    loadPlugin sine;
    (プラグインのパスが設定されていること)
  3. 以下のコマンドでノードを作成する。
    createNode sine -n sine1;
  4. 他のノードとアトリビュートを接続してシーンに組み込む。
    以下の例では、sphere2のtranslateXの値がsin(sphere1.translateX)*10.0になる。
    sphere -n shpere1;
    connectAttr sphere1.tx sine1.input;
    sphere -n shpere2;
    connectAttr sine1.output sphere2.tx;

参考


Prev | Next
Home | Contents
abe@injapan.net