マルチフェーズ カスタム ICENode

 
 
 

マルチフェーズ プロセス モデルでは、シングル フェーズまたはマルチ フェーズのどちらでもカスタム ノードを使用して入力データを処理できます。各フェーズには処理する入力ポートを類似したコンテキストにグループ化して含めることができます。 マルチ フェーズ評価モデルの主な目的は、入力ポートが評価される方法を最適化することです。 たとえば、フェーズ 0 で 1 つのポートを引き出します。次に、それ以降のフェーズで引き出すポートは、フェーズ 0 で読み取ったデータに基づいて決定することができます。

マルチフェーズ評価モードには、次の特徴があります。

制限

  • 引き出すポートは同じコンテキスト タイプを共有する必要があります。共有しない場合はエラーが発生します。 ただし、Singleton コンテキストとフェーズ コンテキストを混在させることはできます。

  • 最終フェーズで引き出すポートは出力ポートのコンテキスト タイプと同一である必要があります。同一でない場合はエラーが発生します。

  • 最終フェーズを除くすべてのフェーズは、ポートを引き出さずに渡すことはできません。

  • Evaluate コールバックからアクセスできるようにするには、最初にポートを引き出す必要があります。

  • SubmitEvaluationPhaseInfo コールバックを渡す必要があります。

警告:

上記のルールを必ず守る必要があります。 守らない場合は、カスタム ノードが不安定になることがあります。

仕組み

次のワークフローは、一般的なマルチフェーズ カスタム ICENode の実装方法を示しています。詳細については、Softimage SDK のインストール ディレクトリにある RandomGridGenerator のサンプルを参照してください。

  1. ノードをマルチフェーズとして登録します

  2. SubmitEvaluationPhaseInfoコールバックを実装します。

  3. Evaluate コールバックを実装します

注:

BeginEvaluate コールバックおよび EndEvaluate コールバックもオプションで、最終評価フェーズ中にのみ呼び出されます。

マルチフェーズ カスタム ノードを登録するには

ICE ノードの定義を使用して、スレッド モデルをマルチフェーズに設定します(siICENodeMultiEvaluationPhase)。

CStatus RegisterMultiPhaseSample( PluginRegistrar& in_reg )
{
	ICENodeDef nodeDef;
	nodeDef = Application().GetFactory().CreateICENodeDef(L"MultiPhaseSample",L"Multi Phase Sample");
	
	CStatus st;
	st = nodeDef.PutThreadingModel(XSI::siICENodeMultiEvaluationPhase);
	st.AssertSucceeded( ) ;
	
	// Add input ports and groups.
	st = nodeDef.AddPortGroup(ID_G_100);
	st.AssertSucceeded( ) ;
	
	st = nodeDef.AddPortGroup(ID_G_102);
	st.AssertSucceeded( ) ;
	
	st = nodeDef.AddPortGroup(ID_G_103);
	st.AssertSucceeded( ) ;
	
	st = nodeDef.AddPortGroup(ID_G_114);
	st.AssertSucceeded( ) ;
	
	st = nodeDef.AddInputPort(ID_IN_condition,ID_G_100,siICENodeDataBool,siICENodeStructureSingle,siICENodeContextSingleton,L"condition",L"condition",true); 
	st.AssertSucceeded( ) ;
	st = nodeDef.AddInputPort(ID_IN_true,ID_G_102,siICENodeDataFloat,siICENodeStructureSingle,siICENodeContextSingleton,L"true",L"true",1.0f);
	st.AssertSucceeded( ) ;
	
	st = nodeDef.AddInputPort(ID_IN_false,ID_G_103,siICENodeDataFloat,siICENodeStructureSingle,siICENodeContextSingleton,L"false",L"false",1.0f);
	st.AssertSucceeded( ) ;
	
	st =nodeDef.AddInputPort(ID_IN_points,ID_G_114,siICENodeDataVector3,siICENodeStructureSingle,siICENodeContextComponent0D|siICENodeContextSingleton,L"points",L"points",MATH::CVector3f(1.0,1.0,1.0));
	st.AssertSucceeded( ) ;
	
	// Add output ports.
	st = nodeDef.AddOutputPort(ID_OUT_results,siICENodeDataVector3,siICENodeStructureSingle,siICENodeContextComponent0D|siICENodeContextSingleton,L"results",L"results");
	st.AssertSucceeded( ) ;
	
	PluginItem nodeItem = in_reg.RegisterICENode(nodeDef);
	nodeItem.PutCategories(L"Custom ICENode");
	return CStatus::OK;
}

SubmitEvaluationPhaseInfoコールバックを実装するには

現在の評価フェーズのために引き出すポートを指定するには、SubmitEvaluationPhaseInfo コールバックが必要です。 このコールバックは ICENodeContext::SetLastEvaluationPhase を使用して現在のフェーズを最終フェーズとしてマークするまで、Softimage によって無限に呼び出されます。

XSIPLUGINCALLBACK CStatus MultiPhaseSample_SubmitEvaluationPhaseInfo( ICENodeContext& in_ctxt )
{
	ULONG nPhase = in_ctxt.GetEvaluationPhaseIndex( );
	switch( nPhase )
	{
		case 0:
		{
			in_ctxt.AddEvaluationPhaseInputPort( ID_IN_condition );
		}
		break;
		
		case 1:
		{
			bool bCondition = (bool)in_ctxt.GetUserData();
			ULONG nPortToPull = bCondition ? ID_IN_true : ID_IN_false;
			in_ctxt.PutUserData( nPortToPull );
			in_ctxt.AddEvaluationPhaseInputPort( nPortToPull );
			in_ctxt.AddEvaluationPhaseInputPort( ID_IN_points );
			// This phase is the last one. All ports specified for phase 1 will be evaluated in multi-threaded batches.
			in_ctxt.SetLastEvaluationPhase();
		}
		break;
	}
	return CStatus::OK;
}

Evaluate コールバックを実装するには

Evaluateコールバックでは、シングルスレッドの中間フェーズの処理とマルチスレッドの最終フェーズを処理できます。

XSIPLUGINCALLBACK CStatus MultiPhaseSample_Evaluate( ICENodeContext& in_ctxt )
{
	// Read the current phase. 
	// Note: ULONG_MAX is returned if the last phase is being processed.
	ULONG nPhase = in_ctxt.GetEvaluationPhaseIndex( );
	
	switch( nPhase )
	{
		case 0:
		{
			CDataArrayBool conditionData( in_ctxt, ID_IN_condition );
			in_ctxt.PutUserData( conditionData[0] );
			return CStatus::OK;
		}
		break;
	};
	
	// Process the output port being evaluated in multi-threading.
	ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID( );
	
	switch( out_portID )
	{
		case ID_OUT_results:
		{
			ULONG nPortToPull = (ULONG)in_ctxt.GetUserData();
			
			CDataArrayFloat scaleValue( in_ctxt, nPortToPull );
			float fScaleValue = scaleValue[0];
			
			CDataArrayVector3f resultsData( in_ctxt );
			CDataArrayVector3f points( in_ctxt, ID_IN_points );
			
			CIndexSet indexSet( in_ctxt );
			for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
			{
				resultsData[it] = points[it];
				resultsData[it] *= fScaleValue;
			}
		}
		break;
	};
	
	return CStatus::OK;
}