マルチフェーズ プロセス モデルでは、シングル フェーズまたはマルチ フェーズのどちらでもカスタム ノードを使用して入力データを処理できます。各フェーズには処理する入力ポートを類似したコンテキストにグループ化して含めることができます。 マルチ フェーズ評価モデルの主な目的は、入力ポートが評価される方法を最適化することです。 たとえば、フェーズ 0 で 1 つのポートを引き出します。次に、それ以降のフェーズで引き出すポートは、フェーズ 0 で読み取ったデータに基づいて決定することができます。
入力コンテキスト タイプを自由に指定できます。ロード時に Softimage によって検証が実行されることはありません。 たとえば、トポロジが異なるまたはデータ セットが異なる(法線とポイントなど)2 つのオブジェクトのポイントへ、同じオブジェクトから接続するように選択できます。
引き出すポートは同じコンテキスト タイプを共有する必要があります。共有しない場合はエラーが発生します。 ただし、Singleton コンテキストとフェーズ コンテキストを混在させることはできます。
最終フェーズで引き出すポートは出力ポートのコンテキスト タイプと同一である必要があります。同一でない場合はエラーが発生します。
SubmitEvaluationPhaseInfo コールバックを渡す必要があります。
以下のワークフローは一般的なマルチフェーズのカスタムICENodeの実装方法を示しています(詳細な例についてはを参照)。
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コールバックでは、シングルスレッドの中間フェーズの処理とマルチスレッドの最終フェーズを処理できます。
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; }